1"use strict";(self.webpackChunkinnovation_labs=self.webpackChunkinnovation_labs||[]).push([[2513],{36591:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>s,toc:()=>d});const s=JSON.parse('{"id":"examples/singularityNet/financial-advisor-agent-metta","title":"Financial Advisor Agent with MeTTa","description":"Learn how to build a toy financial knowledge-lookup agent using MeTTa and SingularityNET","source":"@site/versioned_docs/version-1.0.5/examples/singularityNet/financial-advisor-agent-metta.md","sourceDirName":"examples/singularityNet","slug":"/examples/singularityNet/financial-advisor-agent-metta","permalink":"/resources/docs/examples/singularityNet/financial-advisor-agent-metta","draft":false,"unlisted":false,"tags":[],"version":"1.0.5","frontMatter":{"id":"financial-advisor-agent-metta","title":"Financial Advisor Agent with MeTTa","sidebar_label":"Financial Advisor Agent","description":"Learn how to build a toy financial knowledge-lookup agent using MeTTa and SingularityNET"},"sidebar":"tutorialSidebar","previous":{"title":"Medical Agent with MeTTa","permalink":"/resources/docs/examples/singularityNet/medical-agent-metta"},"next":{"title":"Fetch.ai Knowledge Assistant","permalink":"/resources/docs/examples/singularityNet/fetchai-knowledge-assistant-metta"}}');var r=t(74848),i=t(28453);const o={id:"financial-advisor-agent-metta",title:"Financial Advisor Agent with MeTTa",sidebar_label:"Financial Advisor Agent",description:"Learn how to build a toy financial knowledge-lookup agent using MeTTa and SingularityNET"},a=void 0,l={},d=[{value:"<strong>Overview</strong>",id:"overview",level:2},{value:"<strong>What is MeTTa?</strong>",id:"what-is-metta",level:2},{value:"<strong>Installation & Setup</strong>",id:"installation--setup",level:2},{value:"<strong>Prerequisites</strong>",id:"prerequisites",level:3},{value:"<strong>Installation Options</strong>",id:"installation-options",level:3},{value:"<strong>Option 1: Install All Dependencies at Once (Recommended)</strong>",id:"option-1-install-all-dependencies-at-once-recommended",level:3},{value:"<strong>Option 2: Verify Hyperon First</strong>",id:"option-2-verify-hyperon-first",level:3},{value:"<strong>Windows Installation Guide</strong>",id:"windows-installation-guide",level:3},{value:"<strong>Project layout</strong>",id:"project-layout",level:2},{value:"<strong>Architecture Overview</strong>",id:"architecture-overview",level:2},{value:"<strong>Core Integration Concepts</strong>",id:"core-integration-concepts",level:2},{value:"<strong>1. MeTTa Knowledge Graph Structure</strong>",id:"1-metta-knowledge-graph-structure",level:3},{value:"<strong>2. Pattern Matching and Querying</strong>",id:"2-pattern-matching-and-querying",level:3},{value:"<strong>3. uAgent Chat Protocol Integration</strong>",id:"3-uagent-chat-protocol-integration",level:3},{value:"<strong>4. Knowledge lookup (not vector RAG)</strong>",id:"4-knowledge-lookup-not-vector-rag",level:3},{value:"<strong>Core Components</strong>",id:"core-components",level:2},{value:"<strong>Implementation Guide</strong>",id:"implementation-guide",level:2},{value:"<strong>Step 1: Define Your Knowledge Domain</strong>",id:"step-1-define-your-knowledge-domain",level:3},{value:"<strong>Step 2: Implement MeTTa lookup</strong>",id:"step-2-implement-metta-lookup",level:3},{value:"<strong>Step 3: Query processing</strong>",id:"step-3-query-processing",level:3},{value:"<strong>Step 4: Configure Agent</strong>",id:"step-4-configure-agent",level:3},{value:"<strong>Detailed Working (Step-by-Step)</strong>",id:"detailed-working-step-by-step",level:2},{value:"<strong>Testing and Deployment</strong>",id:"testing-and-deployment",level:2},{value:"<strong>Local Testing (mailbox)</strong>",id:"local-testing-mailbox",level:3},{value:"<strong>Sample queries (aligned with seeded keys)</strong>",id:"sample-queries-aligned-with-seeded-keys",level:3},{value:"<strong>Query your agent from ASI</strong>",id:"query-your-agent-from-asi",level:3},{value:"<strong>Expected output</strong>",id:"expected-output",level:3},{value:"<strong>Notes</strong>",id:"notes",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",hr:"hr",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"overview",children:(0,r.jsx)(n.strong,{children:"Overview"})}),"\n",(0,r.jsxs)(n.p,{children:["This guide shows how to integrate ",(0,r.jsx)(n.strong,{children:"SingularityNET's MeTTa (Meta Type Talk)"})," knowledge graph with ",(0,r.jsx)(n.strong,{children:"Fetch.ai's uAgents"})," framework. The sample is a ",(0,r.jsx)(n.strong,{children:"toy demo"}),": it looks up illustrative risk \u2192 investment \u2192 return / allocation / goal facts in MeTTa, then uses ",(0,r.jsxs)(n.strong,{children:["ASI",":One"]})," to classify intent and humanize the reply. It is ",(0,r.jsx)(n.strong,{children:"not financial advice"}),", ",(0,r.jsx)(n.strong,{children:"not personalized recommendations"}),", and is ",(0,r.jsx)(n.strong,{children:"not a substitute for a licensed advisor"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Shared MeTTa + uAgent template:"})," same layout and safety pattern as ",(0,r.jsx)(n.a,{href:"/docs/examples/singularityNet/medical-agent-metta",children:"Medical Agent with MeTTa"})," and ",(0,r.jsx)(n.a,{href:"/docs/examples/singularityNet/fetchai-knowledge-assistant-metta",children:"Fetch.ai Knowledge Assistant with MeTTa"})," (sibling review: issue ",(0,r.jsx)(n.a,{href:"https://github.com/fetchai/innovationlab-resources/issues/260",children:"#260"}),")."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Tested combo:"})," Python ",(0,r.jsx)(n.strong,{children:"3.10\u20133.12"}),", ",(0,r.jsx)(n.code,{children:"uagents>=0.25.5"})," (needs ",(0,r.jsx)(n.code,{children:"uagents-core"})," 0.4.x), ",(0,r.jsx)(n.code,{children:"hyperon>=0.2.6"}),". Chat Protocol samples need this runtime; Python 3.8 is not supported."]}),"\n",(0,r.jsx)(n.h2,{id:"what-is-metta",children:(0,r.jsx)(n.strong,{children:"What is MeTTa?"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"MeTTa"})," (Meta Type Talk) is SingularityNET's multi-paradigm language for declarative and functional computations over knowledge (meta)graphs. Official docs: ",(0,r.jsx)(n.a,{href:"https://metta-lang.dev/",children:"MeTTa language"})," and ",(0,r.jsx)(n.a,{href:"https://github.com/trueagi-io/hyperon-experimental",children:"Hyperon"}),". It provides:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Structured Knowledge Representation"}),": Organize information in logical, queryable formats"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Symbolic Reasoning"}),": Perform complex logical operations and pattern matching"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Knowledge Graph Operations"}),": Build, query, and manipulate knowledge graphs"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Space-based Architecture"}),": Knowledge stored as atoms in logical spaces"]}
1),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"installation--setup",children:(0,r.jsx)(n.strong,{children:"Installation & Setup"})}),"\n",(0,r.jsx)(n.h3,{id:"prerequisites",children:(0,r.jsx)(n.strong,{children:"Prerequisites"})}),"\n",(0,r.jsx)(n.p,{children:"Before you begin, ensure you have:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Python 3.10+"})," (3.10\u20133.12 recommended for ",(0,r.jsx)(n.code,{children:"uagents"})," 0.25.x). On Windows use ",(0,r.jsx)(n.code,{children:"py -3.10"}),"; on WSL/macOS/Linux use ",(0,r.jsx)(n.code,{children:"python3"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"pip"})," package manager"]}),"\n",(0,r.jsxs)(n.li,{children:["An ",(0,r.jsxs)(n.strong,{children:["ASI",":One"," API key"]})," from the ",(0,r.jsxs)(n.a,{href:"https://asi1.ai/dashboard/api-keys",children:["ASI",":One"," API keys dashboard"]})," (not only the ",(0,r.jsx)(n.a,{href:"https://asi1.ai/",children:"asi1.ai"})," homepage)"]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Create a project folder and a virtual environment (do not install into system Python):"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"# macOS / Linux / WSL\npython3 -m venv .venv\nsource .venv/bin/activate\n\n# Windows PowerShell\npy -3.10 -m venv .venv\n.\\.venv\\Scripts\\Activate.ps1\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Create a ",(0,r.jsx)(n.code,{children:".env"})," file (never commit real secrets):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-text",children:"ASI_ONE_API_KEY=your_key_here\nAGENT_SEED=change-me-to-a-unique-local-seed\n# Optional: set LEARN=1 only if you want the demo to persist LLM guesses into the graph\n# LEARN=1\n"})}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h3,{id:"installation-options",children:(0,r.jsx)(n.strong,{children:"Installation Options"})}),"\n",(0,r.jsx)(n.h3,{id:"option-1-install-all-dependencies-at-once-recommended",children:(0,r.jsx)(n.strong,{children:"Option 1: Install All Dependencies at Once (Recommended)"})}),"\n",(0,r.jsxs)(n.p,{children:["Create a ",(0,r.jsx)(n.code,{children:"requirements.txt"})," file with one package per line:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-text",children:"openai>=1.0.0\nhyperon>=0.2.6\nuagents>=0.25.5\nuagents-core>=0.4.9\npython-dotenv>=1.0.0\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"uagents"}
1)," 0.25.x is tested with ",(0,r.jsx)(n.code,{children:"uagents-core"})," 0.4.x (Chat Protocol). Keep ",(0,r.jsx)(n.code,{children:"uagents>=0.25.5"})," and ",(0,r.jsx)(n.code,{children:"uagents-core>=0.4.9"})," unless you intentionally upgrade the whole stack."]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Install all dependencies with one command:"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"python3 -m pip install -r requirements.txt\n"})}),"\n",(0,r.jsxs)(n.p,{children:["On Windows: ",(0,r.jsx)(n.code,{children:"py -3.10 -m pip install -r requirements.txt"}),"."]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h3,{id:"option-2-verify-hyperon-first",children:(0,r.jsx)(n.strong,{children:"Option 2: Verify Hyperon First"})}),"\n",(0,r.jsxs)(n.p,{children:["Use this only to confirm Hyperon/MeTTa installs on your machine. You still need Option 1 (",(0,r.jsx)(n.code,{children:"requirements.txt"}),") for ",(0,r.jsx)(n.code,{children:"uagents"}),", ",(0,r.jsx)(n.code,{children:"openai"}),", and ",(0,r.jsx)(n.code,{children:"python-dotenv"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"python3 -m pip install hyperon\npython3 -c \"from hyperon import MeTTa; print('Hyperon installed successfully!')\"\n"})}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h3,{id:"windows-installation-guide",children:(0,r.jsx)(n.strong,{children:"Windows Installation Guide"})}),"\n",(0,r.jsxs)(n.p,{children:["Hyperon on native Windows is often painful. ",(0,r.jsx)(n.strong,{children:"WSL (Ubuntu) is recommended."})," If you stay on native Windows and hit build errors, see this video: ",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Hp28F9gL2Cc",children:"Hyperon Installation on Windows"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Written WSL path:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["Install ",(0,r.jsx)(n.a,{href:"https://learn.microsoft.com/en-us/windows/wsl/install",children:"WSL"})," and Ubuntu."]}),"\n",(0,r.jsxs)(n.li,{children:["Inside WSL: install Python 3.10+, create the venv above, then ",(0,r.jsx)(n.code,{children:"pip install -r requirements.txt"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["Run ",(0,r.jsx)(n.code,{children:"python3 agent.py"})," from the project folder shown below."]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"project-layout",children:(0,r.jsx)(n.strong,{children:"Project layout"})}),"\n",(0,r.jsxs)(n.p,{children:["Imports in ",(0,r.jsx)(n.code,{children:"agent.py"})," use the ",(0,r.jsx)(n.code,{children:"metta"})," package. Create this tree (a flat folder of four ",(0,r.jsx)(n.code,{children:".py"})," files will raise ",(0,r.jsx)(n.code,{children:"ImportError"}),"):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-text",children:"project/\n agent.py\n metta/\n __init__.py\n knowledge.py\n investment_rag.py\n utils.py\n .env\n requirements.txt\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Create empty ",(0,r.jsx)(n.code,{children:"metta/__init__.py"}),". Run from ",(0,r.jsx)(n.code,{children:"project/"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"python3 agent.py\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Windows: ",(0,r.jsx)(n.code,{children:"py -3.10 agent.py"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"This page is the canonical sample. Copy the files below into that tree."}),"\n",(0,r.jsx)(n.h2,{id:"architecture-overview",children:(0,r.jsx)(n.strong,{children:"Architecture Overview"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Financial Advisor Agent \u2014 sequence-style workflow (yellow / green / white)",src:t(63935).A+"",width:"1376",height:"768"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.strong,{children:"code"})," pipeline (ASI",":One"," chat does not classify intent for you):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-mermaid",children:"flowchart LR\n user[User or ASI:One chat]\n handler[Chat Protocol handler]\n llm[Agent LLM: intent plus keyword]\n lookup[MeTTa knowledge lookup]\n humanize[Humanize plus disclaimer]\n user --\x3e handler --\x3e llm --\x3e lookup --\x3e humanize --\x3e user\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Alt text: User or ASI",":One"," sends chat text to the Chat Protocol handler. The agent LLM classifies intent and a keyword, MeTTa looks up the toy graph, then the agent humanizes the answer and sends a disclaimer-prefixed reply."]}),"\n",(0,r.jsxs)(n.p,{children:["Architecture pipeline: ",(0,r.jsxs)(n.strong,{children:["User / ASI",":One"," Chat \u2192 Chat Protocol handler \u2192 agent LLM classifies intent + keyword \u2192 MeTTa knowledge lookup (not vector RAG) \u2192 humanized reply with disclaimer \u2192 User"]}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"core-integration-concepts",children:(0,r.jsx)(n.strong,{children:"Core Integration Concepts"})}),"\n",(0,r.jsx)(n.h3,{id:"1-metta-knowledge-graph-structure",children:(0,r.jsx)(n.strong,{children:"1. MeTTa Knowledge Graph Structure"})}),"\n",(0,r.jsxs)(n.p,{children:["MeTTa organizes knowledge as ",(0,r.jsx)(n.strong,{children:"atoms"})," in logical ",(0,r.jsx)(n.strong,{children:"spaces"}),". Use ",(0,r.jsx)(n.strong,{children:"one convention"}),": risk profiles, investment types, age buckets, goals, and FAQ ",(0,r.jsx)(n.em,{children:"keys"})," as ",(0,r.jsx)(n.code,{children:"S(...)"}),"; free-text returns, risk notes, allocations, and FAQ answers as ",(0,r.jsx)(n.code,{children:"ValueAtom"}),". Multi-word names use underscores (",(0,r.jsx)(n.code,{children:"emergency_fund"}),", ",(0,r.jsx)(n.code,{children:"dividend_stocks"}),"), never raw spaces or parentheses inside query interpolation."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:'from hyperon import MeTTa, E, S, ValueAtom\n\nmetta
1= MeTTa()\n\nmetta.space().add_atom(E(S("risk_profile"), S("conservative"), S("bonds")))\nmetta.space().add_atom(\n E(S("expected_return"), S("bonds"), ValueAtom("illustrative 3-5% annually (toy range)"))\n)\nmetta.space().add_atom(\n E(S("faq"), S("amount_to_invest"), ValueAtom("Toy tip: 10-20% of income after an emergency fund."))\n)\n'})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Key MeTTa Elements:"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"E (Expression)"}),": Creates logical expressions"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"S (Symbol)"}),": Represents symbolic atoms (profiles, investment types, FAQ keys)"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"ValueAtom"}),": Stores string values (return ranges, allocation text, FAQ answers)"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Space"}),": Container where atoms are stored and queried"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"2-pattern-matching-and-querying",children:(0,r.jsx)(n.strong,{children:"2. Pattern Matching and Querying"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"# Query syntax: !(match &self (relation subject $variable) $variable)\nquery_str = '!(match &self (risk_profile conservative $investment) $investment)'\nresults = metta.run(query_str)\n# Results include bonds, dividend_stocks, savings_accounts for the toy graph\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Query Components:"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.code,{children:"&self"})}),": References the current space"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.code,{children:"$variable"})}),": Pattern matching variables that capture results"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.code,{children:"!(match ...)"})}),": Query syntax for pattern matching"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Never interpolate unsanitized user/LLM text into MeTTa. Only simple ",(0,r.jsx)(n.code,{children:"[a-z0-9_]+"})," symbols are allowed."]}),"\n",(0,r.jsx)(n.h3,{id:"3-uagent-chat-protocol-integration",children:(0,r.jsx)(n.strong,{children:"3. uAgent Chat Protocol Integration"})}),"\n",(0,r.jsxs)(n.p,{children:["The following is an ",(0,r.jsx)(n.strong,{children:"excerpt"}),". Full Protocol construction is in ",(0,r.jsx)(n.code,{children:"agent.py"}),". ",(0,r.jsx)(n.code,{children:"process_query"})," returns a dict; send the ",(0,r.jsx)(n.code,{children:"humanized_answer"})," string (plus disclaimer), not the dict."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:'from uagents_core.contrib.protocols.chat import (\n ChatMessage,\n ChatAcknowledgement,\n TextContent,\n chat_protocol_spec,\n)\n\n@chat_proto.on_message(ChatMessage)\nasync def handle_message(ctx: Context, sender: str, msg: ChatMessage):\n response = process_query(user_query, rag, llm)\n answer = response.get("humanized_answer", "I could not process that query.")\n await ctx.send(sender, create_text_chat(answer))\n'})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"mailbox=True"})," on ",(0,r.jsx)(n.code,{children:"Agent(...)"})," is the Agentverse mailbox flag (an inbox so a local agent stays reachable). Do ",(0,r.jsx)(n.strong,{children:"not"})," ",(0,r.jsx)(n.code,{children:"import mailbox"})," \u2014 that is Python's stdlib email-mailbox module and is unused here."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"publish_agent_details=True"})," publishes the agent's profile/details to Agentverse when the mailbox connects. Use it for discoverable demos; turn it off if you do not want the profile updated automatically."]}),"\n",(0,r.jsx)(n.h3,{id:"4-knowledge-lookup-not-vector-rag",children:(0,r.jsx)(n.strong,{children:"4. Knowledge lookup (not vector RAG)"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"InvestmentRAG"})," in this sample is a ",(0,r.jsx)(n.strong,{children:"MeTTa retriever"}),": pattern-match on the toy graph, then an LLM humanizes the result. It does ",(0,r.jsx)(n.strong,{children:"not"})," use embeddings or document RAG. The class name is historical; treat it as knowledge lookup. Dynamic graph writes from LLM guesses are ",(0,r.jsx)(n.strong,{children:"off"})," unless ",(0,r.jsx)(n.code,{children:"LEARN=1"})," is set (unsafe for anything beyond a local experiment)."]}),"\n",(0,r.jsx)(n.h2,{id:"core-components",children:(0,r.jsx)(n.strong,{children:"Core Components"})}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.code,{children:"agent.py"})}),": Main uAgent with Chat Protocol"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.code,{children:"metta/knowledge.py"})}),": Toy MeTTa graph (illustrative US-centric teaching data \u2014 not market facts)"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.code,{children:"metta/investment_rag.py"})}),": MeTTa lookup helpers"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.code,{children:"metta/utils.py"})}),": Intent classification and query processing"]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"implementation-guide",children:(0,r.jsx)(n.strong,{children:"Implementation Guide"})}),"\n",(0,r.jsx)(n.h3,{id:"step-1-define-your-knowledge-domain",children:(0,r.jsx)(n.strong,{children:"Step 1: Define Your Knowledge Domain"})}),"\n",(0,r.jsxs)(n.p,{children:["Create ",(0,r.jsx)(n.code,{children:"metta/knowledge.py"}),". Seed edges use ",(0,r.jsx)(n.strong,{children:"symbols"})," for investment types under ",(0,r.jsx)(n.code,{children:"risk_profile"}),", and ",(0,r.jsx)(n.strong,{children:"ValueAtom"})," for free-text returns, risk notes, allocations, strategies, sector examples, mistakes, and FAQs. FAQ keys must match ",(0,r.jsx)(n.code,{children:"query_faq"})," (not the raw user sentence)."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:'from hyperon import MeTTa, E, S, ValueAtom\n\n\ndef initialize_investment_knowledge(metta: MeTTa):\n """Toy graph for the tutorial. Not financial advice or market data."""\n # Risk profile \u2192 investment types (symbols)\n metta.space().add_atom(E(S("risk_profile"), S("conservative"), S("bonds")))\n metta.space().add_atom(E(S("risk_profile"), S("conservative"), S("dividend_stocks")))\n metta.space().add_atom(E(S("risk_profile"), S("conservative"), S("savings_accounts")))\n metta.space().add_atom(E(S("risk_profile"), S("moderate"), S("index_funds")))\n metta.space().add_atom(E(S("risk_profile"), S("moderate"), S("etfs")))\n metta.space().add_atom(E(S("risk_profile"), S("moderate"), S("real_estate")))\n metta.space().add_atom(E(S("risk_profile"), S("aggressive"), S("growth_stocks")))\n metta.space().add_atom(E(S("risk_profile"), S("aggressive"), S("cryptocurrency")))\n metta.space().add_atom(E(S("risk_profile"), S("aggressive"), S("options")))\n\n # Investment \u2192 illustrative return ranges (not forecasts)\n metta.space().add_atom(\n E(S("expected_return"), S("bonds"), ValueAtom("illustrative 3-5% annually (toy range)"))\n )\n metta.space().add_atom(\n E(\n S("expected_return"),\n S("dividend_stocks"),\n ValueAtom("illustrative 5-7% annually (toy range)"),\n )\n )\n metta.space().add_atom(\n E(\n S("expected_return"),\n S("index_funds"),\n ValueAtom("illustrative 6-10% annually (toy range)"),\n )\n )\n metta.space().add_atom(\n E(S("expected_return"), S("etfs"), ValueAtom("illustrative 5-12% annually (toy range)"))\n )\n metta.space().add_atom(\n E(\n S("expected_return"),\n S("growth_stocks"),\n ValueAtom("illustrative 8-15% annually (toy range)"),\n )\n )\n metta.space().add_atom(\n E(\n S("expected_return"),\n S("cryptocurrency"),\n ValueAtom("illustrative: highly volatile (toy label)"),\n )\n )\n metta.space().add_atom(\n E(\n S("expected_return"),\n S("savings_accounts"),\n ValueAtom("illustrative 1-2% annually (toy range)"),\n )\n )\n metta.space().add_atom(\n E(\n S("expected_return"),\n S("real_estate"),\n ValueAtom("illustrative 4-8% annually (toy range)"),\n )\n )\n metta.space().add_atom(\n E(\n S("expected_return"),\n S("options"),\n ValueAtom("illustrative: high risk, leveraged (toy label)"),\n )\n )\n\n # Investment \u2192 risk notes (softened; US-centric toy wording)\n metta.space().add_atom(\n E(S("risk_level"), S("bonds"), ValueAtom("typically lower volatility in this toy graph"))\n )\n metta.space().add_atom(\n E(\n S("risk_level"),\n S("dividend_stocks"),\n ValueAtom("low-moderate risk label in this toy graph"),\n )\n )\n metta.space().add_atom(\n E(S("risk_level"), S("index_funds"), ValueAtom("moderate risk, diversified (toy label)"))\n )\n metta.space().add_atom(\n E(S("risk_level"), S("etfs"), ValueAtom("low-moderate risk, liquid (toy label)"))\n )\n metta.space().add_atom(\n E(S("risk_level"), S("growth_stocks"), V
1alueAtom("higher risk label in this toy graph"))\n )\n metta.space().add_atom(\n E(\n S("risk_level"),\n S("cryptocurrency"),\n ValueAtom("very high risk / volatility (toy label)"),\n )\n )\n metta.space().add_atom(\n E(\n S("risk_level"),\n S("savings_accounts"),\n ValueAtom(\n "often treated as low risk in teaching examples; "\n "deposit insurance rules vary by country (US FDIC is one example only)"\n ),\n )\n )\n metta.space().add_atom(\n E(S("risk_level"), S("real_estate"), ValueAtom("moderate risk label (toy)"))\n )\n metta.space().add_atom(\n E(S("risk_level"), S("options"), ValueAtom("very high risk / leveraged (toy label)"))\n )\n\n # Age \u2192 simplified teaching allocations only (not advice)\n metta.space().add_atom(\n E(\n S("age_allocation"),\n S("20s"),\n ValueAtom("teaching example only: 80% stocks, 20% bonds"),\n )\n )\n metta.space().add_atom(\n E(\n S("age_allocation"),\n S("30s"),\n ValueAtom("teaching example only: 70% stocks, 30% bonds"),\n )\n )\n metta.space().add_atom(\n E(\n S("age_allocation"),\n S("40s"),\n ValueAtom("teaching example only: 60% stocks, 40% bonds"),\n )\n )\n metta.space().add_atom(\n E(\n S("age_allocation"),\n S("50s"),\n ValueAtom("teaching example only: 50% stocks, 50% bonds"),\n )\n )\n metta.space().add_atom(\n E(\n S("age_allocation"),\n S("60s"),\n ValueAtom("teaching example only: 40% stocks, 60% bonds"),\n )\n )\n\n # Goals \u2192 strategies\n metta.space().add_atom(\n E(\n S("goal_strategy"),\n S("retirement"),\n ValueAtom("toy: diversified index funds; retirement-account contributions"),\n )\n )\n metta.space().add_atom(\n E(\n S("goal_strategy"),\n S("emergency_fund"),\n ValueAtom("toy: high-yield savings / money market style cash buffer"),\n )\n )\n metta.space().add_atom(\n E(\n S("goal_strategy"),\n S("house_down_payment"),\n ValueAtom("toy: short-duration cash / short-term bonds"),\n )\n )\n metta.space().add_atom(\n E(\n S("goal_strategy"),\n S("wealth_building"),\n ValueAtom("toy: growth-oriented diversified equity exposure"),\n )\n )\n metta.space().add_atom(\n E(\n S("goal_strategy"),\n S("passive_income"),\n ValueAtom("toy: dividend stocks / bonds style examples"),\n )\n )\n\n # Sector \u2192 illustrative example companies (not current top performers)\n metta.space().add_atom(\n E(\n S("sector_stocks"),\n S("technology"),\n ValueAtom("illustrative names only: Apple, Microsoft, Google"),\n )\n )\n metta.space().add_atom(\n E(\n S("sector_stocks"),\n S("healthcare"),\n ValueAtom("illustrative names only: Johnson & Johnson, Pfizer"),\n )\n )\n metta.space().add_atom(\n E(\n S("sector_stocks"),\n S("finance"),\n ValueAtom("illustrative names only: JPMorgan Chase, Berkshire Hathaway"),\n )\n )\n metta.space().add_atom(\n E(\n S("sector_stocks"),\n S("energy"),\n ValueAtom("illustrative names only: ExxonMobil, Chevron"),\n )\n )\n\n # Common mistakes\n metta.space().add_atom(\n E(\n S("mistake"),\n S("timing_market"),\n ValueAtom("toy warning: avoid trying to time peaks and valleys"),\n )\n )\n metta.space().add_atom(\n E(\n S("mistake"),\n S("lack_diversification"),\n ValueAtom("toy warning: don\'t put all money in one stock or sector"),\n )\n )\n metta.space().add_atom(\n E(\n S("mistake"),\n S("emotional_trading"),\n ValueAtom("toy warning: avoid panic selling or FOMO buying"),\n )\n )\n metta.space().add_atom(\n E(\n S("mistake"),\n S("high_fees"),\n ValueAtom("toy warning: watch expensive product fees"),\n )\n )\n\n # FAQ keys must match query_faq (not the raw user sentence)\n metta.space().add_atom(\n E(\n S("faq"),\n S("amount_to_invest"),\n ValueAtom(\n "Toy tip only: some teaching materials mention 10-20% of income "\n "after an emergency fund. Not personalized advice."\n ),\n )\n )\n metta.space().add_atom(\n E(\n S("faq"),\n S("when_to_start"),\n ValueAtom(\n "Toy tip only: starting early is often cited for compounding demos. "\n "Not personalized advice."\n ),\n )\n )\n metta.space().add_atom(\n E(\n S("faq"),\n S("diversification"),\n ValueAtom(\n "Toy definition: spreading exposure across assets to reduce "\n "single-name risk. Not personalized advice."\n ),\n )\n )\n metta.space().add_atom(\n E(\n S("faq"),\n S("debt_first"),\n ValueAtom(\n "Toy tip only: high-interest debt is often prioritized before "\n "investing in teaching examples. Not personalized advice."\n ),\n )\n )\n metta.space().add_atom(\n E(\n S("faq"),\n S("hi"),\n ValueAtom("Hello! Ask about risk profiles, returns, allocation, or goals in this toy demo."),\n )\n )\n'})}),"\n",(0,r.jsxs)(n.p,{children:["Worked FAQ example: user says ",(0,r.jsx)(n.code,{children:"How much should I invest?"})," \u2192 classifier keyword ",(0,r.jsx)(n.code,{children:"amount_to_invest"})," \u2192 graph key ",(0,r.jsx)(n.code,{children:"amount_to_invest"})," \u2192 seeded answer."]}
1),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Expected keyword forms"})," (normalize before MeTTa): ",(0,r.jsx)(n.code,{children:"conservative"})," / ",(0,r.jsx)(n.code,{children:"moderate"})," / ",(0,r.jsx)(n.code,{children:"aggressive"}),"; age buckets ",(0,r.jsx)(n.code,{children:"20s"}),"\u2013",(0,r.jsx)(n.code,{children:"60s"})," (map \u201c30-year-old\u201d \u2192 ",(0,r.jsx)(n.code,{children:"30s"}),"); goals ",(0,r.jsx)(n.code,{children:"retirement"}),", ",(0,r.jsx)(n.code,{children:"emergency_fund"}),"; sectors ",(0,r.jsx)(n.code,{children:"technology"}),"; FAQ keys above."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Limitation:"})," the classifier extracts ",(0,r.jsx)(n.strong,{children:"one"})," keyword. Sample queries below use a single focus term."]}),"\n",(0,r.jsx)(n.h3,{id:"step-2-implement-metta-lookup",children:(0,r.jsx)(n.strong,{children:"Step 2: Implement MeTTa lookup"})}),"\n",(0,r.jsxs)(n.p,{children:["Create ",(0,r.jsx)(n.code,{children:"metta/investment_rag.py"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:'import re\nfrom hyperon import MeTTa, E, S, ValueAtom\n\nSYMBOL_PATTERN = re.compile(r"^[a-z0-9_]+$")\n\n# Map common natural-language fragments to seeded keys\nKEYWORD_ALIASES = {\n "30-year-old": "30s",\n "30_year_old": "30s",\n "thirty": "30s",\n "20-year-old": "20s",\n "40-year-old": "40s",\n "50-year-old": "50s",\n "60-year-old": "60s",\n "emergency fund": "emergency_fund",\n "down payment": "house_down_payment",\n "how_much_should_i_invest": "amount_to_invest",\n "when_should_i_start_investing": "when_to_start",\n "what_is_diversification": "diversification",\n "should_i_pay_off_debt_first": "debt_first",\n}\n\n\ndef to_symbol(token: str):\n """Encode multi-word names; reject tokens that would break MeTTa."""\n if token is None:\n return None\n raw = str(token).strip().strip(\'"\').lower().replace("\'", "").replace("\\u2019", "")\n if raw in KEYWORD_ALIASES:\n return KEYWORD_ALIASES[raw]\n symbol = raw.replace(" ", "_").replace("-", "_")\n if symbol in KEYWORD_ALIASES:\n return KEYWORD_ALIASES[symbol]\n if not SYMBOL_PATTERN.fullmatch(symbol):\n return None\n return symbol\n\n\ndef atom_to_str(atom) -> str:\n """Parse both Symbol and ValueAtom results."""\n try:\n obj = atom.get_object()\n if obj is not None and hasattr(obj, "value"):\n return str(obj.value)\n except Exception:\n pass\n return str(atom).strip(\'"\')\n\n\nclass InvestmentRAG:\n """MeTTa knowledge lookup (not embedding / vector RAG)."""\n\n def __init__(self, metta_instance: MeTTa):\n self.metta = metta_instance\n\n def _run_match(self, relation: str, subject: str):\n symbol = to_symbol(subject)\n if not symbol:\n return []\n query_str = f"!(match &self ({relation} {symbol} $x) $x)"\n results = self.metta.run(query_str)\n if not results:\n return []\n values = []\n for row in results:\n if row and len(row) > 0:\n values.append(atom_to_str(row[0]))\n return list(dict.fromkeys(values))\n\n def query_risk_profile(self, risk_profile):\n return self._run_match("risk_profile", risk_profile)\n\n def get_expected_return(self, investment):\n return self._run_match("expected_return", investment)\n\n def get_risk_level(self, investment):\n return self._run_match("risk_level", investment)\n\n def get_age_allocation(self, age_group):\n return self._run_match("age_allocation", age_group)\n\n def get_goal_strategy(self, goal):\n return self._run_match("goal_strategy", goal)\n\n def query_sector_stocks(self, sector):\n return self._run_match("sector_stocks", sector)\n\n def get_mistake_warning(self, mistake):\n return self._run_match("mistake", mistake)\n\n def query_faq(self, question_or_key):\n key = to_symbol(question_or_key)\n if not key:\n return None\n results = self._run_match("faq", key)\n return results[0] if results else None\n\n def add_knowledge(self, relation_type, subject, object_value):\n """S
1ame atom conventions as seed data. Used only when LEARN=1."""\n rel = to_symbol(relation_type)\n subj = to_symbol(subject)\n if not rel or not subj or object_value is None:\n return "Skipped invalid knowledge"\n\n if rel == "risk_profile":\n # One atom per investment type symbol (matches seed)\n parts = [\n to_symbol(p)\n for p in str(object_value).replace(",", " ").split()\n if to_symbol(p)\n ]\n if not parts:\n return "Skipped invalid investment symbols"\n for obj in parts:\n self.metta.space().add_atom(E(S(rel), S(subj), S(obj)))\n return f"Added {rel}: {subj} -> {\', \'.join(parts)}"\n\n atom_obj = ValueAtom(str(object_value))\n self.metta.space().add_atom(E(S(rel), S(subj), atom_obj))\n return f"Added {rel}: {subj} -> {object_value}"\n'})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Key Methods:"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.code,{children:"query_risk_profile()"})}),": Investment type symbols for a profile"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsxs)(n.strong,{children:[(0,r.jsx)(n.code,{children:"get_expected_return()"})," / ",(0,r.jsx)(n.code,{children:"get_risk_level()"})]}),": Illustrative ValueAtom text"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsxs)(n.strong,{children:[(0,r.jsx)(n.code,{children:"get_age_allocation()"})," / ",(0,r.jsx)(n.code,{children:"get_goal_strategy()"})]}),": Teaching examples"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.code,{children:"query_sector_stocks()"})}),": Illustrative company names (not live performance)"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.code,{children:"query_faq()"})}),": FAQ by stable key (",(0,r.jsx)(n.code,{children:"amount_to_invest"}),", ",(0,r.jsx)(n.code,{children:"hi"}),"), not the raw sentence"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.code,{children:"add_knowledge()"})}),": Same atom types as seed data (used only when ",(0,r.jsx)(n.code,{children:"LEARN=1"}),")"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"step-3-query-processing",children:(0,r.jsx)(n.strong,{children:"Step 3: Query processing"})}),"\n",(0,r.jsxs)(n.p,{children:["Create ",(0,r.jsx)(n.code,{children:"metta/utils.py"}),". Fallback ",(0,r.jsx)(n.code,{children:"if not prompt:"})," sits at ",(0,r.jsx)(n.strong,{children:"function scope"})," after all intent branches. Default path does ",(0,r.jsx)(n.strong,{children:"not"})," write LLM output into the graph."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"create_completion"})," uses a smaller ",(0,r.jsx)(n.code,{children:"max_tokens"})," (about ",(0,r.jsx)(n.strong,{children:"200"}),") for short JSON intent classification and a larger budget (about ",(0,r.jsx)(n.strong,{children:"300\u2013800"}),") when humanizing a full reply \u2014 intent only needs a tiny JSON object; answers need room for the disclaimer and explanation."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:'import json\nimport os\n\nfrom openai import OpenAI\n\nfrom .investment_rag import InvestmentRAG, to_symbol\n\nDISCLAIMER = (\n "Not financial advice. This is a toy MeTTa demo for education only, "\n "not personalized recommendations or a substitute for a licensed advisor."\n)\nLEARN = os.getenv("LEARN") == "1"\n\n\nclass LLM:\n def __init__(self, api_key):\n self.client = OpenAI(\n api_key=api_key,\n base_url="https://api.asi1.ai/v1",\n )\n\n def create_completion(self, prompt, max_tokens=800):\n completion = self.client.chat.completions.create(\n messages=[{"role": "user", "content": prompt}],\n model="asi1",\n max_tokens=max_tokens,\n )\n return completion.choices[0].message.content\n\n\ndef get_intent_and_keyword(query, llm):\n """Agent-side ASI:One call: classify intent and extract one keyword."""\n prompt = (\n f"Given the investment query: \'{query}\'\\n"\n "Classify the intent as one of: \'risk_profile\', \'investment_advice\', "\n "\'returns\', \'allocation\', \'goal\', \'sector\', \'mistake\', \'faq\', or \'unknown\'.\\n"\n "Extract one keyword as a snake_case graph key.\\n"\n "Age phrases like \'30-year-old\' must become \'30s\' (also 20s/40s/50s/60s).\\n"\n "Goals: retirement, emergency_fund, house_down_payment, wealth_building, passive_income.\\n"\n "FAQs: amount_to_invest, when_to_start, diversification, debt_first; greetings \u2192 hi.\\n"\n "Risk profiles: conservative, moderate, aggressive.\\n"\n "Return *only* JSON:\\n"\n \'{ "intent": "<classified_intent>", "keyword": "<extracted_keyword>" }\'\n )\n response = llm.create_completion(prompt, max_tokens=200)\n try:\n cleaned = response.strip()\n if cleaned.startswith("```"):\n cleaned = "\\n".join(cleaned.split("\\n")[1:])\n if cleaned.endswith("```"):\n cleaned = "\\n".join(cleaned.split("\\n")[:-1])\n result = json.loads(cleaned.strip())\n return result["intent"], result.get("keyword")\n except (json.JSONDecodeError, KeyError):\n return "unknown", None\n\n\ndef generate_knowledge_response(query, intent, keyword, llm):\n """Optional LLM guess. Do not persist unless LEARN=1."""\n if intent == "risk_profile":\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Risk profile \'{keyword}\' is missing from the toy graph. Suggest 2-3 "\n f"snake_case investment type tokens (e.g. bonds index_funds). Return only those tokens."\n )\n elif intent == "investment_advice":\n prompt = (\n f"Query: \'{query}\'\\n"\n f"No graph notes for \'{keyword}\'. Give a one-sentence educational overview "\n f"(not personalized advice). Return only that text."\n )\n elif intent == "returns":\n prompt = (\n f"Query: \'{query}\'\\n"\n f"No illustrative return range for \'{keyword}\'. Suggest one short toy range "\n f"labeled as illustrative only. Return only that text."\n )\n elif intent == "allocation":\n prompt = (\n f"Query: \'{query}\'\\n"\n f"No teaching allocation for \'{keyword}\'. Suggest one simplified stocks/bonds "\n f"example labeled teaching-only. Return only that text."\n )\n elif intent == "goal":\n prompt = (\n f"Query: \'{query}\'\\n"\n f"No strategy for \'{keyword}\'. Suggest one short educational approach. Return only that text."\n )\n elif intent == "sector":\n prompt = (\n f"Query: \'{query}\'\\n"\n f"No illustrative names for \'{keyword}\'. Suggest a few example companies "\n f"(not performance claims). Return only a short list."\n )\n elif intent == "mistake":\n prompt = (\n f"Query: \'{query}\'\\n"\n f"No warning for \'{keyword}\'. Give one short educational caution. Return only that text."\n )\n elif intent == "faq":\n prompt = (\n f"Query: \'{query}\'\\n"\n "Provide a concise educational overview and remind the user this is not financial advice. "\n "Return only the answer."\n )\n else:\n return None\n return llm.create_completion(prompt, max_tokens=200)\n\n\ndef process_query(query, rag: InvestmentRAG, llm: LLM):\n intent, keyword = get_intent_and_keyword(query, llm)\n
1keyword = to_symbol(keyword) if keyword else None\n prompt = ""\n\n if intent == "faq":\n faq_key = keyword or to_symbol(query)\n faq_answer = rag.query_faq(faq_key) if faq_key else None\n if faq_answer:\n prompt = (\n f"Query: \'{query}\'\\n"\n f"FAQ Answer: \'{faq_answer}\'\\n"\n "Humanize with a friendly educational tone. Keep not-financial-advice meaning."\n )\n else:\n new_answer = generate_knowledge_response(query, intent, keyword, llm)\n if LEARN and faq_key and new_answer:\n rag.add_knowledge("faq", faq_key, new_answer)\n prompt = (\n f"Query: \'{query}\'\\n"\n f"FAQ Answer: \'{new_answer}\'\\n"\n "Humanize with a friendly educational tone. This is not financial advice."\n )\n elif intent == "risk_profile" and keyword:\n investments = rag.query_risk_profile(keyword)\n if not investments:\n investment_types = generate_knowledge_response(query, intent, keyword, llm)\n if LEARN and investment_types:\n rag.add_knowledge("risk_profile", keyword, investment_types)\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Risk Profile: {keyword}\\n"\n f"Suitable Investments (unverified LLM suggestion, not a graph fact): {investment_types}\\n"\n "Be explicit this is a toy educational overview, not recommendations."\n )\n else:\n investment_details = []\n for investment in investments:\n returns = rag.get_expected_return(investment)\n risks = rag.get_risk_level(investment)\n investment_details.append(\n {\n "type": investment,\n "returns": returns[0] if returns else "N/A",\n "risks": risks[0] if risks else "N/A",\n }\n )\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Risk Profile: {keyword}\\n"\n f"Investment Options (toy graph): {investment_details}\\n"\n "Give an educational overview only. Label returns as illustrative ranges."\n )\n elif intent == "returns" and keyword:\n returns = rag.get_expected_return(keyword)\n risks = rag.get_risk_level(keyword)\n if not returns:\n return_info = generate_knowledge_response(query, intent, keyword, llm)\n if LEARN and return_info:\n rag.add_knowledge("expected_return", keyword, return_info)\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Investment: {keyword}\\n"\n f"Expected Returns (unverified LLM suggestion): {return_info}\\n"\n "Say this is not a forecast and not from the verified toy graph."\n )\n else:\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Investment: {keyword}\\n"\n f"Illustrative return ranges (toy graph, not forecasts): {\', \'.join(returns)}\\n"\n f"Risk notes: {\', \'.join(risks) if risks else \'Not specified\'}\\n"\n "Explain as educational ranges only."\n )\n elif intent == "allocation" and keyword:\n allocation = rag.get_age_allocation(keyword)\n if not allocation:\n allocation_advice = generate_knowledge_response(query, intent, keyword, llm)\n if LEARN and allocation_advice:\n rag.add_knowledge("age_allocation", keyword, allocation_advice)\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Age Group: {keyword}\\n"\n f"Allocation (unverified LLM suggestion): {allocation_advice}\\n"\n "Label as a simplified teaching example only."\n )\n else:\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Age Group: {keyword}\\n"\n f"Teaching allocation example: {\', \'.join(allocation)}\\n"\n "Explain as a simplified classroom example, not advice."\n )\n elif intent == "goal" and keyword:\n strategies = rag.get_goal_strategy(keyword)\n if not strategies:\n strategy = generate_knowledge_response(query, intent, keyword, llm)\n if LEARN and strategy:\n rag.add_knowledge("goal_strategy", keyword, strategy)\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Investment Goal: {keyword}\\n"\n f"Strategy (unverified LLM suggestion): {strategy}\\n"\n "Educational overview only."\n )\n else:\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Investment Goal: {keyword}\\n"\n f"Toy strategies: {\', \'.join(strategies)}\\n"\n "Educational overview only."\n )\n elif intent == "sector" and keyword:\n stocks = rag.query_sector_stocks(keyword)\n if not stocks:\n sector_info = generate_knowledge_response(query, intent, keyword, llm)\n if not sector_info:\n sector_info = (\n "No specific names generated; consider diversified sector funds in real life "\n "(this demo is not advice)."\n )\n elif LEARN:\n rag.add_knowledge("sector_stocks", keyword, sector_info)\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Sector: {keyword}\\n"\n f"Illustrative names: {sector_info}\\n"\n "Do not claim current performance rankings."\n )\n else:\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Sector: {keyword}\\n"\n f"Illustrative example companies (not top performers / not recommendations): "\n f"{\', \'.join(stocks)}\\n"\n "Educational naming only."\n )\n elif intent == "investment_advice" and keyword:\n exp = rag.get_expected_return(keyword)\n risks = rag.get_risk_level(keyword)\n if exp or risks:\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Investment type: {keyword}\\n"\n f"Illustrative returns (toy graph): {\', \'.join(exp) if exp else \'N/A\'}\\n"\n f"Risk notes (toy graph): {\', \'.join(risks) if risks else \'N/A\'}\\n"\n "Educational overview only; not a recommendation."\n )\n else:\n advice = generate_knowledge_response(query, intent, keyword, llm)\n if not advice:\n advice = (\n "Consider diversified, low-cost options aligned with your horizon in real life; "\n "consult a licensed professional for personal advice."\n )\n # investment_advice does not invent new graph edges unless LEARN=1\n # and you choose to store expected_return text for consistency\n if LEARN and advice:\n rag.add_knowledge("expected_return", keyword, advice)\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Investment type: {keyword}\\n"\n f"Guidance: {advice}\\n"\n "Educational overview only; not a recommendation."\n )\n elif intent == "mistake" and keyword:\n warnings = rag.get_mistake_warning(keyword)\n if warnings:\n wtext = ", ".join(warnings)\n else:\n wtext = generate_knowledge_response(query, intent, keyword, llm)\n if not wtext:\n wtext = (\n "Prioritize diversification, discipline, and awareness of fees and emotions "\n "(toy teaching note)."\n )\n elif LEARN:\n rag.add_knowledge("mistake", keyword, wtext)\n prompt = (\n f"Query: \'{query}\'\\n"\n f"Topic / behavior: {keyword}\\n"\n f"Warning(s): {wtext}\\n"\n "Explain clearly as educational caution, not personalized advice."\n )\n\n if not prompt:\n prompt = (\n f"Query: \'{query}\'\\n"\n "No specific info found in the toy graph. Offer general educational assistance "\n "and suggest consulting a licensed financial professional."\n )\n\n prompt += (\n f"\\nAlways start the answer with: {DISCLAIMER}\\n"\n "Then give the helpful educational content. Do not invent personalized buy/sell orders."\n )\n response = llm.create_completion(prompt, max_tokens=800)\n text = (response or "").strip()\n if DISCLAIMER.lower() not in text.lower():\n text = f"{DISCLAIMER}\\n\\n{text}"\n return {"selected_question": query, "humanized_answer": text}\n'})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Intent Classification (runs in the agent, after Chat Protocol receives text):"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"risk_profile"}),": keyword \u2192 investment type symbols in the toy graph"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"returns"})," / ",(0,r.jsx)(n.strong,{children:"investment_advice"}),": illustrative return / risk notes"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"allocation"}),": age keys ",(0,r.jsx)(n.code,{children:"20s"}),"\u2026",(0,r.jsx)(n.code,{children:"60s"})," (teaching examples)"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"goal"})," / ",(0,r.jsx)(n.strong,{children:"sector"})," / ",(0,r.jsx)(n.strong,{children:"mistake"}),": keyed strategies, illustrative names, warnings"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"faq"}),": keyed FAQs (",(0,r.jsx)(n.code,{children:"amount_to_invest"}),", ",(0,r.jsx)(n.code,{children:"when_to_start"}),", ",(0,r.jsx)(n.code,{children:"diversification"}),", ",(0,r.jsx)(n.code,{children:"debt_first"}),", ",(0,r.jsx)(n.code,{children:"hi"}),")"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"step-4-configure-agent",children:(0,r.jsx)(n.strong,{children:"Step 4: Configure Agent"})}),"\n",(0,r.jsxs)(n.p,{children:["Create ",(0,r.jsx)(n.code,{children:"agent.py"})," at the project root (not inside ",(0,r.jsx)(n.code,{children:"metta/"}),"):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:'from datetime import datetime, timezone\nfrom uuid import uuid4\nimport os\nimport sys\n\nfrom dotenv import load_dotenv\nfrom uagents import Context, Protocol, Agent\nfrom hyperon import MeTTa\n\nfrom uagents_core.contrib.protocols.chat import (\n ChatAcknowledgement,\n ChatMessage,\n EndSessionContent,\n StartSessionContent,\n TextContent,\n chat_protocol_spec,\n)\n\nfrom metta.investment_rag import InvestmentRAG\nfrom metta.knowledge import initialize_investment_knowledge\nfrom metta.utils import LLM, process_query, DISCLAIMER\n\nload_dotenv()\n\napi_key = os.getenv("ASI_ONE_API_KEY")\nagent_seed = os.getenv("AGENT_SEED")\n\nif not api_key:\n print("Missing ASI_ONE_API_KEY. Create a key at https://asi1.ai/dashboard/api-keys and put it in .env")\n sys.exit(1)\n\nif not agent_seed:\n print("Missing AGENT_SEED. Set a unique local seed in .env (do not commit secrets).")\n sys.exit(1)\n\nagent = Agent(\n name="Financial Investment Advisor",\n seed=agent_seed,\n port=8008,\n mailbox=True,\n publish_agent_details=True,\n)\n\n\ndef create_text_chat(text: str, end_session: bool = False) -> ChatMessage:\n content = [TextContent(type="text", text=text)]\n if end_session:\n content.append(EndSessionContent(type="end-session"))\n return ChatMessage(\n timestamp=datetime.now(timezone.utc),\n msg_id=uuid4(),\n content=content,\n )\n\n\nmetta
1= MeTTa()\ninitialize_investment_knowledge(metta)\nrag = InvestmentRAG(metta)\nllm = LLM(api_key=api_key)\n\nchat_proto = Protocol(spec=chat_protocol_spec)\n\n\n@chat_proto.on_message(ChatMessage)\nasync def handle_message(ctx: Context, sender: str, msg: ChatMessage):\n ctx.storage.set(str(ctx.session), sender)\n await ctx.send(\n sender,\n ChatAcknowledgement(\n timestamp=datetime.now(timezone.utc),\n acknowledged_msg_id=msg.msg_id,\n ),\n )\n\n for item in msg.content:\n if isinstance(item, StartSessionContent):\n ctx.logger.info(f"Got a start session message from {sender}")\n continue\n elif isinstance(item, TextContent):\n user_query = item.text.strip()\n ctx.logger.info(f"Got an investment query from {sender}: {user_query}")\n try:\n response = process_query(user_query, rag, llm)\n answer_text = response.get(\n "humanized_answer",\n f"{DISCLAIMER}\\n\\nI could not process your query.",\n )\n await ctx.send(sender, create_text_chat(answer_text))\n except Exception as e:\n ctx.logger.error(f"Error processing investment query: {e}")\n await ctx.send(\n sender,\n create_text_chat(\n f"{DISCLAIMER}\\n\\nI hit an error processing that query. Please try again."\n ),\n )\n else:\n ctx.logger.info(f"Got unexpected content from {sender}")\n\n\n@chat_proto.on_message(ChatAcknowledgement)\nasync def handle_ack(ctx: Context, sender: str, msg: ChatAcknowledgement):\n ctx.logger.info(\n f"Got an acknowledgement from {sender} for {msg.acknowledged_msg_id}"\n )\n\n\nagent.include(chat_proto, publish_manifest=True)\n\nif __name__ == "__main__":\n agent.run()\n'})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Agent Features:"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Toy MeTTa lookup only \u2014 ",(0,r.jsx)(n.strong,{children:"not"})," a financial advisor product or personalized advice"]}),"\n",(0,r.jsxs)(n.li,{children:["Every reply includes a ",(0,r.jsx)(n.strong,{children:"not financial advice"})," disclaimer"]}),"\n",(0,r.jsxs)(n.li,{children:["Does ",(0,r.jsx)(n.strong,{children:"not"})," persist unverified LLM output into the graph unless ",(0,r.jsx)(n.code,{children:"LEARN=1"})]}),"\n",(0,r.jsxs)(n.li,{children:["Agent LLM (ASI",":One",") classifies intent after Chat Protocol receives text"]}),"\n",(0,r.jsxs)(n.li,{children:["Compatible with ASI",":One"," via Chat Protocol and Agentverse mailbox (",(0,r.jsx)(n.code,{children:"mailbox=True"}),")"]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"detailed-working-step-by-step",children:(0,r.jsx)(n.strong,{children:"Detailed Working (Step-by-Step)"})}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["User sends a query through ASI",":One"," chat (or Inspector chat)."]}),"\n",(0,r.jsxs)(n.li,{children:["Chat Protocol handler receives ",(0,r.jsx)(n.code,{children:"TextContent"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["The ",(0,r.jsx)(n.strong,{children:"agent"})," calls ASI",":One"," (",(0,r.jsx)(n.code,{children:"get_intent_and_keyword"}),") to classify intent and one keyword."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"InvestmentRAG"})," runs MeTTa ",(0,r.jsx)(n.code,{children:"match"})," queries on the toy graph (knowledge lookup, not vector RAG)."]}),"\n",(0,r.jsxs)(n.li,{children:["Reply is humanized, disclaimer is prepended, and Chat Protocol sends a ",(0,r.jsx)(n.strong,{children:"string"})," (not a dict)."]}),"\n",(0,r.jsxs)(n.li,{children:["Graph writes from LLM guesses happen ",(0,r.jsx)(n.strong,{children:"only"})," when ",(0,r.jsx)(n.code,{children:"LEARN=1"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"testing-and-deployment",children:(0,r.jsx)(n.strong,{children:"Testing and Deployment"})}),"\n",(0,r.jsx)(n.h3,{id:"local-testing-mailbox",children:(0,r.jsx)(n.strong,{children:"Local Testing (mailbox)"})}),"\n",(0,r.jsxs)(n.p,{children:["Numbered steps matching current uAgents + Agentverse. See also ",(0,r.jsx)(n.a,{href:"/docs/agent-creation/uagent-creation#mailbox-agents",children:"Mailbox agents"})," and ",(0,r.jsx)(n.a,{href:"/docs/agent-creation/uagent-creation",children:"uAgent creation"}),"."]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Log in to ",(0,r.jsx)(n.a,{href:"https://agentverse.ai",children:"Agentverse"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["From ",(0,r.jsx)(n.code,{children:"project/"}),", with venv active and ",(0,r.jsx)(n.code,{children:".env"})," set:"]}
1),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"python3 agent.py\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Windows: ",(0,r.jsx)(n.code,{children:"py -3.10 agent.py"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"In the console, copy the inspector URL (it includes your agent address). Expected lines look like:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-text",children:"INFO: [Financial Investment Advisor]: Starting agent with address: agent1q...\nINFO: [Financial Investment Advisor]: Agent inspector available at https://agentverse.ai/inspect/?uri=http%3A//127.0.0.1%3A8008&address=agent1q...\nINFO: [Financial Investment Advisor]: Starting mailbox client for https://agentverse.ai\nINFO: [mailbox]: Successfully registered as mailbox agent in Agentverse\n"})}),"\n",(0,r.jsxs)(n.p,{children:["If you see ",(0,r.jsx)(n.code,{children:"Missing ASI_ONE_API_KEY"}),", stop and fix ",(0,r.jsx)(n.code,{children:".env"})," \u2014 the agent exits before ",(0,r.jsx)(n.code,{children:"agent.run()"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Open the inspector URL while logged in. Choose ",(0,r.jsx)(n.strong,{children:"Connect"})," \u2192 ",(0,r.jsx)(n.strong,{children:"Mailbox"})," (Agentverse issues the mailbox token; you do not paste Python ",(0,r.jsx)(n.code,{children:"import mailbox"}),")."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.strong,{children:"Chat with Agent"})," on the Inspector/profile, or continue to ASI",":One"," below. Keep ",(0,r.jsx)(n.code,{children:"agent.py"})," running."]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"sample-queries-aligned-with-seeded-keys",children:(0,r.jsx)(n.strong,{children:"Sample queries (aligned with seeded keys)"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"Hi"})," \u2192 FAQ key ",(0,r.jsx)(n.code,{children:"hi"})," (greeting)"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"How much should I invest?"})," \u2192 FAQ key ",(0,r.jsx)(n.code,{children:"amount_to_invest"})," (seeded FAQ)"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"I am a conservative investor, what should I invest in?"})," \u2192 risk profile ",(0,r.jsx)(n.code,{children:"conservative"})," \u2192 ",(0,r.jsx)(n.code,{children:"bonds"}),", ",(0,r.jsx)(n.code,{children:"dividend_stocks"}),", ",(0,r.jsx)(n.code,{children:"savings_accounts"})]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"What returns can I expect from index funds?"})," \u2192 illustrative ranges for ",(0,r.jsx)(n.code,{children:"index_funds"})]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"How should a 30-year-old allocate a portfolio?"})," \u2192 age key ",(0,r.jsx)(n.code,{children:"30s"})," (teaching example)"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"What strategy works best for retirement?"})," \u2192 goal ",(0,r.jsx)(n.code,{children:"retirement"})]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"What are common investing mistakes to avoid?"})," \u2192 mistake keys such as ",(0,r.jsx)(n.code,{children:"timing_market"})," / ",(0,r.jsx)(n.code,{children:"lack_diversification"})," (one keyword per turn)"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"query-your-agent-from-asi",children:(0,r.jsxs)(n.strong,{children:["Query your agent from ASI",":One"]})}),"\n",(0,r.jsxs)(n.p,{children:["ASI",":One"," discovers mailbox agents that are running, registered, and using Chat Protocol. README/handle tips: ",(0,r.jsx)(n.a,{href:"/docs/agentverse/searching-agents",children:"Searching agents"}),". Chat UI: ",(0,r.jsxs)(n.a,{href:"https://chat.asi1.ai/",children:["ASI",":One"," Chat"]}),"."]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["Copy the agent address from the console (",(0,r.jsx)(n.code,{children:"agent1q..."}),"). Optionally set a handle on the Agentverse profile."]}),"\n",(0,r.jsxs)(n.li,{children:["Open ",(0,r.jsxs)(n.a,{href:"https://asi1.ai/",children:["ASI",":One"]}),", sign in with Google or the ASI",":One"," wallet, and start a new chat."]}),"\n",(0,r.jsxs)(n.li,{children:["Toggle ",(0,r.jsx)(n.strong,{children:"Agents"})," so ASI",":One"," can call Agentverse agents."]}),"\n",(0,r.jsxs)(n.li,{children:["Paste the address or ",(0,r.jsx)(n.code,{children:"@handle"})," and send a sample query such as ",(0,r.jsx)(n.code,{children:"I am a conservative investor, what should I invest in?"})]}),"\n",(0,r.jsxs)(n.li,{children:["Expect a reply that starts with the not-financial-a
1dvice disclaimer and mentions toy graph options such as ",(0,r.jsx)(n.strong,{children:"bonds"})," / ",(0,r.jsx)(n.strong,{children:"dividend_stocks"})," / ",(0,r.jsx)(n.strong,{children:"savings_accounts"}),". The local console should log the incoming chat message."]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"expected-output",children:(0,r.jsx)(n.strong,{children:"Expected output"})}),"\n",(0,r.jsxs)(n.p,{children:["Startup (shape of logs; address is unique to your ",(0,r.jsx)(n.code,{children:"AGENT_SEED"}),"):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-text",children:"INFO: [Financial Investment Advisor]: Starting agent with address: agent1q...\nINFO: [Financial Investment Advisor]: Agent inspector available at https://agentverse.ai/inspect/?uri=...\nINFO: [mailbox]: Successfully registered as mailbox agent in Agentverse\n"})}),"\n",(0,r.jsx)(n.p,{children:"Example chat:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"You:"})," ",(0,r.jsx)(n.code,{children:"How much should I invest?"})]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Agent:"})," Starts with ",(0,r.jsx)(n.em,{children:"Not financial advice..."})," then, from the toy FAQ key ",(0,r.jsx)(n.code,{children:"amount_to_invest"}),", gives the seeded educational tip (not a personalized plan)."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"You:"})," ",(0,r.jsx)(n.code,{children:"I am a conservative investor, what should I invest in?"})]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Agent:"})," Starts with the disclaimer, then lists toy-graph options like ",(0,r.jsx)(n.code,{children:"bonds"}),", ",(0,r.jsx)(n.code,{children:"dividend_stocks"}),", and ",(0,r.jsx)(n.code,{children:"savings_accounts"})," with illustrative return/risk notes."]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"notes",children:(0,r.jsx)(n.strong,{children:"Notes"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Educational toy demo only \u2014 ",(0,r.jsx)(n.strong,{children:"not"})," personalized financial advice."]}),"\n",(0,r.jsxs)(n.li,{children:["Default path does ",(0,r.jsx)(n.strong,{children:"not"})," persist unverified LLM financial \u201cfacts\u201d; set ",(0,r.jsx)(n.code,{children:"LEARN=1"})," only for local experiments."]}),"\n",(0,r.jsx)(n.li,{children:"For production usage, add compliance rules, disclosure controls, and policy guardrails."}),"\n",(0,r.jsxs)(n.li,{children:["Sibling MeTTa samples: ",(0,r.jsx)(n.a,{href:"/docs/examples/singularityNet/medical-agent-metta",children:"Medical Agent with MeTTa"}),", ",(0,r.jsx)(n.a,{href:"/docs/examples/singularityNet/fetchai-knowledge-assistant-metta",children:"Fetch.ai Knowledge Assistant with MeTTa"}),"."]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},63935:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/financial-advisor-workflow-88363a3a9f72ba8f759da3f347e124a5.png"},28453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>a});var s=t(96540);const r={},i=s.createContext(r);function o(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.