Skip to main content

Strands Research Agent

Research assistant with MCP web-fetch tools, a LiteLLM-backed model, and snapshot-based checkpointing.

Difficulty: Intermediate

What You'll Learn

  • Explicit framework selection via mav-agent-config.yaml — the one place this field is load-bearing rather than an override
  • register_agent() for schema extraction and runner resolution
  • MCP tool integration via agentvisor.strands.mcp.get_mcp_tools()
  • LiteLLM-backed model configuration — AgentVisor's proven production route to Bedrock
  • Snapshot-based multi-turn conversation via agent.take_snapshot()/load_snapshot()
  • Credential brokering for ANTHROPIC_API_KEY (never exposed in the sandbox)

Setup

agentvisor template create strands/research-agent
cd research-agent

export ANTHROPIC_API_KEY=your-api-key-here
temporal server start-dev &
agentvisor serve . --sandbox=none

Test It

THREAD=$(curl -sX POST http://localhost:8090/threads | jq -r '.thread_id')

# Research a topic
curl -sX POST "http://localhost:8090/threads/$THREAD/runs?wait=120s" \
-H "Content-Type: application/json" \
-d '{"input": {"message": "Research the history of the Python programming language"}}' \
| jq '.output'

# Follow-up — agent remembers the previous research via its Strands snapshot
curl -sX POST "http://localhost:8090/threads/$THREAD/runs?wait=120s" \
-H "Content-Type: application/json" \
-d '{"input": {"message": "What were the key design decisions that made Python popular?"}}' \
| jq '.output'

How It Works

  1. Selection: mav-agent-config.yaml explicitly sets framework.provider: "strands" — Strands has no discovery file for AgentVisor to auto-detect
  2. Execution: python3 -m agentvisor.strands.runner resolves root_agent from agent.py
  3. Callback silencing: The runner replaces Strands' default stdout-printing callback handler with a no-op, since it would otherwise corrupt the runner's JSON output contract
  4. Research: The agent calls MCP fetch tools → MCP Gateway → policy check → mcp-server-fetch (stdio) → content returned
  5. Model calls: LiteLLM routes requests to api.anthropic.com through the AgentVisor HTTP proxy for credential substitution
  6. State persistence: agent.take_snapshot(preset="session") is saved via checkpoint.save() after each run and restored via checkpoint.load("")/agent.load_snapshot() on the next run in the same thread

Credential Flow

Agent (Strands Agent + LiteLLMModel)
└─► LiteLLM → api.anthropic.com
└─► Guest Proxy (TLS termination)
└─► Host Proxy (token substitution: ANTHROPIC_API_KEY)
└─► api.anthropic.com (real key)

The real ANTHROPIC_API_KEY is never visible inside the guest sandbox.

Checkpointing

AspectDetail
Mechanismagent.take_snapshot(preset="session") / agent.load_snapshot()
Storageagentvisor.checkpoint.save()/load(), Temporal-backed, per thread
ScopeOne snapshot per thread — "session" preset covers messages, state, conversation_manager_state, interrupt_state, model_state
CompatibilityNot cross-compatible with the LangGraph AgentVisorCheckpointer — see Checkpointing

Project Files

strands/research-agent/
├── agent.py # Root agent: Strands Agent with MCP fetch tools
├── mav-agent-config.yaml # REQUIRED: selects the strands framework provider
├── requirements.txt # Python dependencies
├── agentvisor.yaml # AgentVisor config (proxy creds + MCP server)
└── policies/
└── domain.yml # Authorization policies

mav-agent-config.yaml

framework:
provider: "strands"

agent.py (key section)

from strands import Agent
from strands.models.litellm import LiteLLMModel
from agentvisor.strands import register_agent
from agentvisor.strands.mcp import get_mcp_tools

root_agent = Agent(
name="researcher",
model=LiteLLMModel(client_args={}, model_id="anthropic/claude-haiku-4-5-20251001"),
system_prompt="...",
tools=get_mcp_tools("fetch"),
)
register_agent(root_agent)

LiteLLMModel is used here rather than a direct Anthropic or Bedrock model — it's AgentVisor's proven production route to Bedrock, and this example simply points it at Anthropic's API directly for a runnable demo with no AWS credentials required. See the Strands Agents Guide for the full model-provider guidance, including why raw BedrockModel/boto3 is a documented known limitation behind AgentVisor's TLS-terminating proxy.

Next Steps