Files
agentlens/examples/multi_agent.py

184 lines
5.9 KiB
Python

"""
AgentLens Multi-Agent Example — Nested traces for orchestrated agent workflows.
Demonstrates:
- A "planner" agent that delegates to sub-agents
- Nested trace contexts that create parent-child span relationships automatically
- Multiple decision types: ROUTING, PLANNING, TOOL_SELECTION
- How the dashboard shows the full agent call tree
Usage:
pip install vectry-agentlens
python multi_agent.py
"""
import agentlens
import time
# Initialize
agentlens.init(
api_key="your-api-key-here",
endpoint="http://localhost:4200",
)
def simulate_llm_call(prompt: str, delay: float = 0.2) -> str:
"""Fake LLM call — replace with real model calls in production."""
time.sleep(delay)
return f"[LLM response to: {prompt[:50]}...]"
# Top-level planner agent trace
with agentlens.trace("planner-agent", tags=["multi-agent", "blog-pipeline"]):
# Planner decides the workflow
agentlens.log_decision(
type="PLANNING",
chosen={
"name": "research_then_write",
"confidence": 0.93,
"params": {
"steps": ["research", "outline", "draft", "review"],
"topic": "AI agents in production",
},
},
alternatives=[
{
"name": "write_directly",
"confidence": 0.4,
"reason_rejected": "Topic requires research for factual accuracy",
},
],
reasoning="Complex topic — research phase needed before writing.",
)
# Planner routes to researcher agent
agentlens.log_decision(
type="ROUTING",
chosen={
"name": "researcher-agent",
"confidence": 0.95,
"params": {"query": "AI agents in production best practices 2025"},
},
alternatives=[
{
"name": "writer-agent",
"confidence": 0.3,
"reason_rejected": "Need facts before drafting",
},
],
reasoning="Researcher goes first to gather source material.",
)
# --- Nested: Researcher Agent ---
with agentlens.trace("researcher-agent", tags=["research"]):
agentlens.log_decision(
type="TOOL_SELECTION",
chosen={
"name": "web_search",
"confidence": 0.88,
"params": {
"query": "AI agents production deployment 2025",
"limit": 10,
},
},
alternatives=[
{
"name": "arxiv_search",
"confidence": 0.72,
"reason_rejected": "Need industry examples, not just papers",
},
],
reasoning="Web search covers blog posts, case studies, and papers.",
)
research_results = simulate_llm_call(
"Summarize findings about AI agents in production"
)
agentlens.log_decision(
type="MEMORY_RETRIEVAL",
chosen={
"name": "store_research_context",
"confidence": 0.9,
"params": {"key": "research_findings", "chunks": 5},
},
alternatives=[],
reasoning="Store condensed findings for the writer agent to consume.",
)
# Planner routes to writer agent
agentlens.log_decision(
type="ROUTING",
chosen={
"name": "writer-agent",
"confidence": 0.97,
"params": {"style": "technical-blog", "word_count": 1500},
},
alternatives=[
{
"name": "researcher-agent",
"confidence": 0.15,
"reason_rejected": "Research phase complete, enough material gathered",
},
],
reasoning="Research complete — hand off to writer with gathered material.",
)
# --- Nested: Writer Agent ---
with agentlens.trace("writer-agent", tags=["writing"]):
agentlens.log_decision(
type="PLANNING",
chosen={
"name": "structured_outline_first",
"confidence": 0.91,
"params": {
"sections": ["intro", "challenges", "solutions", "conclusion"]
},
},
alternatives=[
{
"name": "stream_of_consciousness",
"confidence": 0.3,
"reason_rejected": "Technical blog needs clear structure",
},
],
reasoning="Outline-first approach produces better organized blog posts.",
)
outline = simulate_llm_call("Create blog outline for AI agents in production")
draft = simulate_llm_call("Write full blog draft from outline", delay=0.5)
# --- Nested deeper: Editor sub-agent within writer ---
with agentlens.trace("editor-agent", tags=["editing"]):
agentlens.log_decision(
type="TOOL_SELECTION",
chosen={
"name": "grammar_check",
"confidence": 0.85,
"params": {"text_length": 1500, "style_guide": "technical"},
},
alternatives=[
{
"name": "skip_editing",
"confidence": 0.1,
"reason_rejected": "Always edit before publishing",
},
],
reasoning="Run grammar and style check on the draft.",
)
edited = simulate_llm_call("Edit and polish the blog draft", delay=0.3)
print("Blog pipeline complete!")
print(f"Research: {research_results}")
print(f"Final draft: {edited}")
# Shutdown
agentlens.shutdown()
print("\nDone! Check AgentLens dashboard — you'll see nested spans:")
print(" planner-agent")
print(" -> researcher-agent")
print(" -> writer-agent")
print(" -> editor-agent")