This sample demonstrates an agent using the Marvin framework to extract structured contact information from text, integrated with the Agent2Agent (A2A) protocol.
The agent receives text, attempts to extract contact details (name, email, phone, etc.) into a structured format using Marvin. It manages conversational state across multiple turns to gather required information (name, email) before confirming the extracted data. The agent's response includes both a textual summary/question and the structured data via A2A.
- Marvin
ExtractorAgent(agent.py): Core logic usingmarvinfor extraction and managing multi-turn state via a dictionary. - A2A
AgentTaskManager(task_manager.py): Integrates the agent with the A2A protocol, managing task state (including streaming via SSE) and response formatting. - A2A Server (
__main__.py): Hosts the agent and task manager.
- Python 3.12+
- uv
OPENAI_API_KEY(or other LLM provider creds supported by pydantic-ai)
-
Navigate to the Python samples directory:
cd samples/python/agents/marvin -
Set an LLM provider API key:
export OPENAI_API_KEY=your_api_key_here -
Set up the Python environment:
uv venv source .venv/bin/activate uv sync -
Run the Marvin agent server:
# Default host/port (localhost:10030) MARVIN_DATABASE_URL=sqlite+aiosqlite:///test.db MARVIN_LOG_LEVEL=DEBUG uv run . # Custom host/port # uv run . --host 0.0.0.0 --port 8080
Without
MARVIN_DATABASE_URLset, conversation history will not be persisted by session id. -
In a separate terminal, run an A2A client (e.g., the sample CLI):
# Ensure the environment is active (source .venv/bin/activate) cd samples/python/hosts/cli uv run . --agent http://localhost:10030 # Use the correct agent URL/port
The structured data returned in the DataPart is defined as:
class ContactInfo(BaseModel):
name: str = Field(description="Person's first and last name")
email: EmailStr
phone: str = Field(description="standardized phone number")
organization: str | None = Field(None, description="org if mentioned")
role: str | None = Field(None, description="title or role if mentioned")with a validator to render things nicely if you want and maybe serialize weird things.