Skip to main content
Version: Next

Medical Agent with MeTTa

Overview

This guide shows how to integrate SingularityNET's MeTTa (Meta Type Talk) knowledge graph with Fetch.ai's uAgents framework. The sample is a toy demo: it looks up illustrative symptom → disease → treatment → side-effect facts in MeTTa, then uses ASI:One to classify intent and humanize the reply. It is not medical advice and is not a substitute for professional care.

Tested combo: Python 3.10–3.12, uagents>=0.22.5 (needs uagents-core 0.3.x), hyperon>=0.2.6. Chat Protocol samples need this runtime; Python 3.8 is not supported.

What is MeTTa?

MeTTa (Meta Type Talk) is SingularityNET's multi-paradigm language for declarative and functional computations over knowledge (meta)graphs. Official docs: MeTTa language and Hyperon. It provides:

  • Structured Knowledge Representation: Organize information in logical, queryable formats
  • Symbolic Reasoning: Perform complex logical operations and pattern matching
  • Knowledge Graph Operations: Build, query, and manipulate knowledge graphs
  • Space-based Architecture: Knowledge stored as atoms in logical spaces

Installation & Setup

Prerequisites

Before you begin, ensure you have:

  • Python 3.10+ (3.10–3.12 recommended for uagents 0.22.x). On Windows use py -3.10; on WSL/macOS/Linux use python3.
  • pip package manager
  • An ASI:One API key from the ASI:One API keys dashboard (not only the asi1.ai homepage)

Create a project folder and a virtual environment (do not install into system Python):

# macOS / Linux / WSL
python3 -m venv .venv
source .venv/bin/activate

# Windows PowerShell
py -3.10 -m venv .venv
.\.venv\Scripts\Activate.ps1

Create a .env file (never commit real secrets):

ASI_ONE_API_KEY=your_key_here
AGENT_SEED=change-me-to-a-unique-local-seed
# Optional: set LEARN=1 only if you want the demo to persist LLM guesses into the graph
# LEARN=1

Installation Options

Create a requirements.txt file with one package per line:

openai>=1.0.0
hyperon>=0.2.6
uagents>=0.22.5
uagents-core>=0.3.5,<0.4.0
python-dotenv>=1.0.0

uagents 0.22.x is tested with uagents-core 0.3.x (Chat Protocol). Newer uagents 0.23.x needs uagents-core>=0.4.0; keep the pins above unless you upgrade the whole stack.

Install all dependencies with one command:

python3 -m pip install -r requirements.txt

On Windows: py -3.10 -m pip install -r requirements.txt.


Option 2: Verify Hyperon First

Use this only to confirm Hyperon/MeTTa installs on your machine. You still need Option 1 (requirements.txt) for uagents, openai, and python-dotenv.

python3 -m pip install hyperon
python3 -c "from hyperon import MeTTa; print('Hyperon installed successfully!')"

Windows Installation Guide

Hyperon on native Windows is often painful. WSL (Ubuntu) is recommended. If you stay on native Windows and hit build errors, see this video: Hyperon Installation on Windows.

Written WSL path:

  1. Install WSL and Ubuntu.
  2. Inside WSL: install Python 3.10+, create the venv above, then pip install -r requirements.txt.
  3. Run python3 agent.py from the project folder shown below.

Project layout

Imports in agent.py use the metta package. Create this tree (a flat folder of four .py files will raise ImportError):

project/
agent.py
metta/
__init__.py
knowledge.py
medicalrag.py
utils.py
.env
requirements.txt

Create empty metta/__init__.py. Run from project/:

python3 agent.py

Windows: py -3.10 agent.py.

This page is the canonical sample. Copy the files below into that tree.

Architecture Overview

Medical Agent — sequence-style workflow (yellow / green / white)

The code pipeline (ASI:One chat does not classify intent for you):

flowchart LR
user[User or ASI:One chat]
handler[Chat Protocol handler]
llm[Agent LLM: intent plus keyword]
lookup[MeTTa knowledge lookup]
humanize[Humanize plus disclaimer]
user --> handler --> llm --> lookup --> humanize --> user

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.

Architecture pipeline: User / ASI:One Chat → Chat Protocol handler → agent LLM classifies intent + keyword → MeTTa knowledge lookup (not vector RAG) → humanized reply with disclaimer → User.

Core Integration Concepts

1. MeTTa Knowledge Graph Structure

MeTTa organizes knowledge as atoms in logical spaces. Use one convention: diseases, symptoms, and treatment keys as S(...); free-text FAQ answers as ValueAtom. Multi-word names use underscores (stomach_upset), never raw spaces or parentheses inside query interpolation.

from hyperon import MeTTa, E, S, ValueAtom

metta = MeTTa()

metta.space().add_atom(E(S("symptom"), S("fever"), S("flu")))
metta.space().add_atom(E(S("treatment"), S("flu"), S("antiviral_drugs")))
metta.space().add_atom(E(S("side_effect"), S("antiviral_drugs"), ValueAtom("nausea, dizziness")))
metta.space().add_atom(E(S("faq"), S("hi"), ValueAtom("Hello! How can I assist you today?")))

Key MeTTa Elements:

  • E (Expression): Creates logical expressions
  • S (Symbol): Represents symbolic atoms
  • ValueAtom: Stores string values (FAQ text, side-effect descriptions)
  • Space: Container where atoms are stored and queried

2. Pattern Matching and Querying

# Query syntax: !(match &self (relation subject $variable) $variable)
query_str = '!(match &self (symptom fever $disease) $disease)'
results = metta.run(query_str)
# Results include flu for the toy graph

Query Components:

  • &self: References the current space
  • $variable: Pattern matching variables that capture results
  • !(match ...): Query syntax for pattern matching

Never interpolate unsanitized user/LLM text into MeTTa. Only simple [a-z0-9_]+ symbols are allowed.

3. uAgent Chat Protocol Integration

The following is an excerpt. Full Protocol construction is in agent.py. process_query returns a dict; send the humanized_answer string (plus disclaimer), not the dict.

from uagents_core.contrib.protocols.chat import (
ChatMessage,
ChatAcknowledgement,
TextContent,
chat_protocol_spec,
)

@chat_proto.on_message(ChatMessage)
async def handle_message(ctx: Context, sender: str, msg: ChatMessage):
response = process_query(user_query, rag, llm)
answer = response.get("humanized_answer", "I could not process that query.")
await ctx.send(sender, create_text_chat(answer))

mailbox=True on Agent(...) is the Agentverse mailbox flag (an inbox so a local agent stays reachable). Do not import mailbox — that is Python's stdlib email-mailbox module and is unused here.

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.

4. Knowledge lookup (not vector RAG)

MedicalRAG in this sample is a MeTTa retriever: pattern-match on the toy graph, then an LLM humanizes the result. It does not use embeddings or document RAG. Dynamic graph writes from LLM guesses are off unless LEARN=1 is set (unsafe for anything beyond a local experiment).

Core Components

  1. agent.py: Main uAgent with Chat Protocol
  2. metta/knowledge.py: Toy MeTTa graph (illustrative only — not clinical knowledge)
  3. metta/medicalrag.py: MeTTa lookup helpers
  4. metta/utils.py: Intent classification and query processing

Implementation Guide

Step 1: Define Your Knowledge Domain

Create metta/knowledge.py. Edges are only symptom → disease, disease → treatment, treatment → side_effect, plus FAQ keys. Treatments are separate atoms so side-effect lookup works (for example antiviral_drugs, not one mashed string).

from hyperon import MeTTa, E, S, ValueAtom


def initialize_knowledge_graph(metta: MeTTa):
"""Toy graph for the tutorial. Not clinical knowledge."""
# Symptoms → diseases
metta.space().add_atom(E(S("symptom"), S("fever"), S("flu")))
metta.space().add_atom(E(S("symptom"), S("cough"), S("flu")))
metta.space().add_atom(E(S("symptom"), S("nausea"), S("flu")))
metta.space().add_atom(E(S("symptom"), S("headache"), S("migraine")))
metta.space().add_atom(E(S("symptom"), S("dizziness"), S("migraine")))
metta.space().add_atom(E(S("symptom"), S("anxiety"), S("depression")))
metta.space().add_atom(E(S("symptom"), S("insomnia"), S("depression")))

# Diseases → treatments (one atom per treatment key)
metta.space().add_atom(E(S("treatment"), S("flu"), S("rest")))
metta.space().add_atom(E(S("treatment"), S("flu"), S("fluids")))
metta.space().add_atom(E(S("treatment"), S("flu"), S("antiviral_drugs")))
metta.space().add_atom(E(S("treatment"), S("migraine"), S("pain_relievers")))
metta.space().add_atom(E(S("treatment"), S("migraine"), S("hydration")))
metta.space().add_atom(E(S("treatment"), S("migraine"), S("dark_room")))
metta.space().add_atom(E(S("treatment"), S("depression"), S("therapy")))
metta.space().add_atom(E(S("treatment"), S("depression"), S("antidepressants")))

# Treatments → side effects
metta.space().add_atom(
E(S("side_effect"), S("antiviral_drugs"), ValueAtom("nausea, dizziness"))
)
metta.space().add_atom(
E(S("side_effect"), S("pain_relievers"), ValueAtom("stomach_upset"))
)
metta.space().add_atom(
E(S("side_effect"), S("antidepressants"), ValueAtom("weight_gain, insomnia"))
)

# FAQ keys must match query_faq (not the raw user sentence)
metta.space().add_atom(
E(S("faq"), S("hi"), ValueAtom("Hello! How can I assist you today?"))
)
metta.space().add_atom(
E(
S("faq"),
S("not_a_doctor"),
ValueAtom(
"I am not a doctor. This is a toy demo, not medical advice. "
"See a clinician for diagnosis or treatment."
),
)
)
metta.space().add_atom(
E(
S("faq"),
S("migraine_treatment"),
ValueAtom(
"In this toy graph, migraine treatments include pain_relievers, "
"hydration, and dark_room."
),
)
)

Worked FAQ example: user says Hi → classifier keyword hi → graph key hi → greeting.

Limitation: the classifier extracts one keyword. Sample queries below use a single symptom (for example fever), not “fever and cough”.

Step 2: Implement MeTTa lookup

Create metta/medicalrag.py:

import re
from hyperon import MeTTa, E, S, ValueAtom

SYMBOL_PATTERN = re.compile(r"^[a-z0-9_]+$")


def to_symbol(token: str):
"""Encode multi-word names; reject tokens that would break MeTTa."""
if token is None:
return None
symbol = (
str(token)
.strip()
.strip('"')
.lower()
.replace("'", "")
.replace("\u2019", "")
.replace(" ", "_")
)
if not SYMBOL_PATTERN.fullmatch(symbol):
return None
return symbol


def atom_to_str(atom) -> str:
"""Parse both Symbol and ValueAtom results."""
try:
obj = atom.get_object()
if obj is not None and hasattr(obj, "value"):
return str(obj.value)
except Exception:
pass
return str(atom).strip('"')


class MedicalRAG:
"""MeTTa knowledge lookup (not embedding RAG)."""

def __init__(self, metta_instance: MeTTa):
self.metta = metta_instance

def _run_match(self, relation: str, subject: str):
symbol = to_symbol(subject)
if not symbol:
return []
query_str = f"!(match &self ({relation} {symbol} $x) $x)"
results = self.metta.run(query_str)
if not results:
return []
values = []
for row in results:
if row and len(row) > 0:
values.append(atom_to_str(row[0]))
return list(dict.fromkeys(values))

def query_symptom(self, symptom):
return self._run_match("symptom", symptom)

def get_treatment(self, disease):
return self._run_match("treatment", disease)

def get_side_effects(self, treatment):
return self._run_match("side_effect", treatment)

def query_faq(self, question_or_key):
key = to_symbol(question_or_key)
if not key:
return None
results = self._run_match("faq", key)
return results[0] if results else None

def add_knowledge(self, relation_type, subject, object_value):
rel = to_symbol(relation_type)
subj = to_symbol(subject)
if not rel or not subj or object_value is None:
return "Skipped invalid knowledge"

if rel == "symptom":
obj = to_symbol(object_value)
if not obj:
return "Skipped invalid disease symbol"
atom_obj = S(obj)
elif rel in ("treatment",):
obj = to_symbol(object_value)
if not obj:
return "Skipped invalid treatment symbol"
atom_obj = S(obj)
else:
atom_obj = ValueAtom(str(object_value))

self.metta.space().add_atom(E(S(rel), S(subj), atom_obj))
return f"Added {rel}: {subj} -> {object_value}"

Key Methods:

  • query_symptom(): Finds diseases for a symbol-safe symptom
  • get_treatment(): Treatment keys for a disease (then look up each key’s side effects)
  • get_side_effects(): Side effects for a treatment key such as antiviral_drugs
  • query_faq(): FAQ by stable key (hi, migraine_treatment), not the raw sentence
  • add_knowledge(): Same atom types as seed data (used only when LEARN=1)

Step 3: Query processing

Create metta/utils.py. Fallback if not prompt: sits at function scope after all intent branches. Default path does not write LLM output into the graph.

import json
import os

from openai import OpenAI

from .medicalrag import MedicalRAG, to_symbol

DISCLAIMER = (
"Not medical advice. I am not a doctor. This is a toy MeTTa demo, "
"not a substitute for professional care."
)
LEARN = os.getenv("LEARN") == "1"


class LLM:
def __init__(self, api_key):
self.client = OpenAI(
api_key=api_key,
base_url="https://api.asi1.ai/v1",
)

def create_completion(self, prompt, max_tokens=800):
completion = self.client.chat.completions.create(
messages=[{"role": "user", "content": prompt}],
model="asi1",
max_tokens=max_tokens,
)
return completion.choices[0].message.content


def get_intent_and_keyword(query, llm):
"""Agent-side ASI:One call: classify intent and extract one keyword."""
prompt = (
f"Given the query: '{query}'\n"
"Classify the intent as one of: 'symptom', 'treatment', 'side effect', 'faq', or 'unknown'.\n"
"Extract the most relevant single keyword (one symptom, disease, or treatment). "
"Use snake_case for multi-word names (e.g. antiviral_drugs).\n"
"For greetings like Hi/Hello, intent=faq and keyword=hi.\n"
"For 'how do I treat a migraine', intent=faq and keyword=migraine_treatment.\n"
"For 'what's wrong with me', intent=faq and keyword=not_a_doctor.\n"
"Return *only* JSON:\n"
'{ "intent": "<classified_intent>", "keyword": "<extracted_keyword>" }'
)
response = llm.create_completion(prompt)
try:
cleaned = response.strip()
if cleaned.startswith("```"):
cleaned = "\n".join(cleaned.split("\n")[1:])
if cleaned.endswith("```"):
cleaned = "\n".join(cleaned.split("\n")[:-1])
result = json.loads(cleaned.strip())
return result["intent"], result.get("keyword")
except (json.JSONDecodeError, KeyError):
return "unknown", None


def generate_knowledge_response(query, intent, keyword, llm):
"""Optional LLM guess. Do not persist unless LEARN=1."""
if intent == "symptom":
prompt = (
f"Query: '{query}'\n"
f"The symptom '{keyword}' is not in the toy graph. Suggest one plausible disease name "
f"as a snake_case token. Return only that token."
)
elif intent == "treatment":
prompt = (
f"Query: '{query}'\n"
f"No treatments for '{keyword}' in the toy graph. Suggest one snake_case treatment key. "
f"Return only that token."
)
elif intent == "side effect":
prompt = (
f"Query: '{query}'\n"
f"No side effects for '{keyword}'. Suggest a short description. Return only that text."
)
elif intent == "faq":
prompt = (
f"Query: '{query}'\n"
"Provide a concise answer and remind the user this is not medical advice. "
"Return only the answer."
)
else:
return None
return llm.create_completion(prompt)


def _side_effects_for_treatments(rag: MedicalRAG, treatments):
chunks = []
for t in treatments:
effects = rag.get_side_effects(t)
if effects:
chunks.append(f"{t}: {', '.join(effects)}")
return "; ".join(chunks) if chunks else "none in toy graph"


def process_query(query, rag: MedicalRAG, llm: LLM):
intent, keyword = get_intent_and_keyword(query, llm)
keyword = to_symbol(keyword) if keyword else None
prompt = ""

if intent == "faq":
faq_key = keyword or to_symbol(query)
faq_answer = rag.query_faq(faq_key) if faq_key else None
if faq_answer:
prompt = (
f"Query: '{query}'\n"
f"FAQ Answer: '{faq_answer}'\n"
"Humanize this with a friendly tone. Keep the not-a-doctor meaning."
)
else:
new_answer = generate_knowledge_response(query, intent, keyword, llm)
if LEARN and faq_key and new_answer:
rag.add_knowledge("faq", faq_key, new_answer)
prompt = (
f"Query: '{query}'\n"
f"FAQ Answer: '{new_answer}'\n"
"Humanize this with a friendly tone. This is not medical advice."
)
elif intent == "symptom" and keyword:
diseases = rag.query_symptom(keyword)
if not diseases:
disease = generate_knowledge_response(query, intent, keyword, llm)
if LEARN and disease:
rag.add_knowledge("symptom", keyword, disease)
treatments = rag.get_treatment(disease) if disease else []
prompt = (
f"Query: '{query}'\n"
f"Symptom: {keyword}\n"
f"Related Disease (unverified LLM suggestion, not a graph fact): {disease}\n"
f"Treatments in graph: {', '.join(treatments) if treatments else 'none'}\n"
"Be explicit that this is a toy demo, not a diagnosis."
)
else:
disease = diseases[0]
treatments = rag.get_treatment(disease)
side_effects = _side_effects_for_treatments(rag, treatments)
prompt = (
f"Query: '{query}'\n"
f"Symptom: {keyword}\n"
f"Related Disease (toy graph): {disease}\n"
f"Treatments: {', '.join(treatments)}\n"
f"Side Effects: {side_effects}\n"
"Generate a concise, empathetic response. Do not claim to diagnose."
)
elif intent == "treatment" and keyword:
treatments = rag.get_treatment(keyword)
if treatments:
prompt = (
f"Query: '{query}'\n"
f"Disease: {keyword}\n"
f"Treatments: {', '.join(treatments)}\n"
"Provide a helpful suggestion from the toy graph only."
)
else:
treatment = generate_knowledge_response(query, intent, keyword, llm)
if LEARN and treatment:
rag.add_knowledge("treatment", keyword, treatment)
prompt = (
f"Query: '{query}'\n"
f"Disease: {keyword}\n"
f"Treatments (unverified LLM suggestion): {treatment}\n"
"Say this is not from the verified toy graph."
)
elif intent == "side effect" and keyword:
side_effects = rag.get_side_effects(keyword)
if side_effects:
prompt = (
f"Query: '{query}'\n"
f"Treatment: {keyword}\n"
f"Side Effects: {', '.join(side_effects)}\n"
"Explain briefly from the toy graph."
)
else:
side_effect = generate_knowledge_response(query, intent, keyword, llm)
if LEARN and side_effect:
rag.add_knowledge("side_effect", keyword, side_effect)
prompt = (
f"Query: '{query}'\n"
f"Treatment: {keyword}\n"
f"Side Effects (unverified LLM suggestion): {side_effect}\n"
"Do not present this as clinical fact."
)

if not prompt:
prompt = (
f"Query: '{query}'\n"
"No specific info found in the toy graph. Offer general assistance "
"and remind the user to see a clinician."
)

prompt += (
f"\nAlways start the answer with: {DISCLAIMER}\n"
"Then give the helpful content. Do not invent prescriptions."
)
response = llm.create_completion(prompt, max_tokens=800)
text = (response or "").strip()
if DISCLAIMER.lower() not in text.lower():
text = f"{DISCLAIMER}\n\n{text}"
return {"selected_question": query, "humanized_answer": text}

Intent Classification (runs in the agent, after Chat Protocol receives text):

  • symptom: one keyword → diseases and treatments in the toy graph
  • treatment: treatments for a disease key
  • side effect: side effects for a treatment key (antiviral_drugs, antidepressants)
  • faq: keyed FAQs (hi, not_a_doctor, migraine_treatment)

Step 4: Configure Agent

Create agent.py at the project root (not inside metta/):

from datetime import datetime, timezone
from uuid import uuid4
import os
import sys

from dotenv import load_dotenv
from uagents import Context, Protocol, Agent
from hyperon import MeTTa

from uagents_core.contrib.protocols.chat import (
ChatAcknowledgement,
ChatMessage,
EndSessionContent,
StartSessionContent,
TextContent,
chat_protocol_spec,
)

from metta.medicalrag import MedicalRAG
from metta.knowledge import initialize_knowledge_graph
from metta.utils import LLM, process_query, DISCLAIMER

load_dotenv()

api_key = os.getenv("ASI_ONE_API_KEY")
agent_seed = os.getenv("AGENT_SEED")

if not api_key:
print("Missing ASI_ONE_API_KEY. Create a key at https://asi1.ai/dashboard/api-keys and put it in .env")
sys.exit(1)

if not agent_seed:
print("Missing AGENT_SEED. Set a unique local seed in .env (do not commit secrets).")
sys.exit(1)

agent = Agent(
name="Medical MeTTa Agent",
seed=agent_seed,
port=8005,
mailbox=True,
publish_agent_details=True,
)


def create_text_chat(text: str, end_session: bool = False) -> ChatMessage:
content = [TextContent(type="text", text=text)]
if end_session:
content.append(EndSessionContent(type="end-session"))
return ChatMessage(
timestamp=datetime.now(timezone.utc),
msg_id=uuid4(),
content=content,
)


metta = MeTTa()
initialize_knowledge_graph(metta)
rag = MedicalRAG(metta)
llm = LLM(api_key=api_key)

chat_proto = Protocol(spec=chat_protocol_spec)


@chat_proto.on_message(ChatMessage)
async def handle_message(ctx: Context, sender: str, msg: ChatMessage):
ctx.storage.set(str(ctx.session), sender)
await ctx.send(
sender,
ChatAcknowledgement(
timestamp=datetime.now(timezone.utc),
acknowledged_msg_id=msg.msg_id,
),
)

for item in msg.content:
if isinstance(item, StartSessionContent):
ctx.logger.info(f"Got a start session message from {sender}")
continue
elif isinstance(item, TextContent):
user_query = item.text.strip()
ctx.logger.info(f"Got a medical query from {sender}: {user_query}")
try:
response = process_query(user_query, rag, llm)
answer_text = response.get(
"humanized_answer",
f"{DISCLAIMER}\n\nI could not process your query.",
)
await ctx.send(sender, create_text_chat(answer_text))
except Exception as e:
ctx.logger.error(f"Error processing medical query: {e}")
await ctx.send(
sender,
create_text_chat(
f"{DISCLAIMER}\n\nI hit an error processing that query. Please try again."
),
)
else:
ctx.logger.info(f"Got unexpected content from {sender}")


@chat_proto.on_message(ChatAcknowledgement)
async def handle_ack(ctx: Context, sender: str, msg: ChatAcknowledgement):
ctx.logger.info(
f"Got an acknowledgement from {sender} for {msg.acknowledged_msg_id}"
)


agent.include(chat_proto, publish_manifest=True)

if __name__ == "__main__":
agent.run()

Agent Features:

  • Toy MeTTa lookup only — not a clinical system or a substitute for care
  • Every reply includes a not medical advice / not a doctor disclaimer
  • Does not persist unverified LLM output into the graph unless LEARN=1
  • Agent LLM (ASI:One) classifies intent after Chat Protocol receives text
  • Compatible with ASI:One via Chat Protocol and Agentverse mailbox (mailbox=True)

Detailed Working (Step-by-Step)

  1. User sends a query through ASI:One chat (or Inspector chat).
  2. Chat Protocol handler receives TextContent.
  3. The agent calls ASI:One (get_intent_and_keyword) to classify intent and one keyword.
  4. MedicalRAG runs MeTTa match queries on the toy graph.
  5. Reply is humanized, disclaimer is prepended, and Chat Protocol sends a string (not a dict).

Testing and Deployment

Local Testing (mailbox)

Numbered steps matching current uAgents + Agentverse. See also Mailbox agents and uAgent creation.

  1. Log in to Agentverse.

  2. From project/, with venv active and .env set:

    python3 agent.py

    Windows: py -3.10 agent.py.

  3. In the console, copy the inspector URL (it includes your agent address). Expected lines look like:

    INFO:     [Medical MeTTa Agent]: Starting agent with address: agent1q...
    INFO: [Medical MeTTa Agent]: Agent inspector available at https://agentverse.ai/inspect/?uri=http%3A//127.0.0.1%3A8005&address=agent1q...
    INFO: [Medical MeTTa Agent]: Starting mailbox client for https://agentverse.ai
    INFO: [mailbox]: Successfully registered as mailbox agent in Agentverse

    If you see Missing ASI_ONE_API_KEY, stop and fix .env — the agent exits before agent.run().

  4. Open the inspector URL while logged in. Choose ConnectMailbox (Agentverse issues the mailbox token; you do not paste Python import mailbox).

  5. Use Chat with Agent on the Inspector/profile, or continue to ASI:One below. Keep agent.py running.

Sample queries (aligned with one-keyword lookup)

  • Hi → FAQ key hi (greeting)
  • I have a fever, what could this indicate? → symptom fever → toy disease flurest, fluids, antiviral_drugs (side effects on antiviral_drugs)
  • What treatment is commonly used for migraine? → treatments for migraine
  • What side effects can antidepressants have? → side effects for antidepressants
  • How do I treat a migraine? → FAQ key migraine_treatment

metta1 metta1 metta1

Query your agent from ASI:One

ASI:One discovers mailbox agents that are running, registered, and using Chat Protocol. README/handle tips: Searching agents. Chat UI: ASI:One Chat.

  1. Copy the agent address from the console (agent1q...). Optionally set a handle on the Agentverse profile.
  2. Open ASI:One, sign in with Google or the ASI:One wallet, and start a new chat.
  3. Toggle Agents so ASI:One can call Agentverse agents.
  4. Paste the address or @handle and send a sample query such as I have a fever, what could this indicate?
  5. Expect a reply that starts with the not-a-doctor disclaimer and mentions the toy flu graph (not a real diagnosis). The local console should log the incoming chat message.

metta1 metta1 metta1

Expected output

Startup (shape of logs; address is unique to your AGENT_SEED):

INFO:     [Medical MeTTa Agent]: Starting agent with address: agent1q...
INFO: [Medical MeTTa Agent]: Agent inspector available at https://agentverse.ai/inspect/?uri=...
INFO: [mailbox]: Successfully registered as mailbox agent in Agentverse

Example chat:

  • You: I have a fever, what could this indicate?
  • Agent: Starts with Not medical advice. I am not a doctor... then, from the toy graph, links feverflu and lists rest, fluids, antiviral_drugs (with nausea/dizziness on antiviral_drugs if asked).