PageSourceSearch

https://innovationlab.fetch.ai/resources/assets/js/82ce7962.059c31c0.js

js fetch.ai collected 2026-10-01 11:56:28 UTC 68,969 bytes, 1 lines download raw bytes

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 &amp; 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.