Skip to main content

Research Agent

Web research with fine-grained API access control.

Difficulty: Advanced

What You'll Learn

  • Annotation-based HTTP policies
  • Internal network blocking
  • Multiple external APIs
  • Per-tool permissions

Available Tools

ToolEndpointPolicy
search_wikipediaen.wikipedia.orgAllowed
fetch_weatherwttr.inAllowed
fetch_urlAny URLMost blocked

Security Features

Internal Network Blocking

The policy blocks:

  • localhost (except Ollama)
  • 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12
  • *.internal, *.local domains

Approved External APIs

Only these are allowed:

  • en.wikipedia.org - Encyclopedia
  • wttr.in - Weather

Setup

agentvisor template create langgraph/research-agent
cd research-agent
docker compose up -d
agentvisor serve .

Test It

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

# Wikipedia (allowed)
curl -sX POST "http://localhost:8090/threads/$THREAD/runs?wait=60s" \
-H "Content-Type: application/json" \
-d '{"input": {"messages": [{"role": "user", "content": "Tell me about quantum computing"}]}}'

# Weather (allowed)
curl -sX POST "http://localhost:8090/threads/$THREAD/runs?wait=60s" \
-H "Content-Type: application/json" \
-d '{"input": {"messages": [{"role": "user", "content": "Whats the weather in London?"}]}}'

# Generic URL (blocked)
curl -sX POST "http://localhost:8090/threads/$THREAD/runs?wait=60s" \
-H "Content-Type: application/json" \
-d '{"input": {"messages": [{"role": "user", "content": "Fetch https://example.com"}]}}'

Policy Highlights

Annotation-Based Patterns

resources:
- name: http-research-endpoints
selector:
- "mrn:agentvisor:http:.*"
group: "mrn:agentvisor:resourcegroup:http-research"
annotations:
- name: "allowed_patterns"
value:
- "^en\\.wikipedia\\.org(/.*)?$"
- "^wttr\\.in(/.*)?$"
- name: "blocked_patterns"
value:
- ".*\\.internal$"
- "metadata\\.google\\..*"

Internal Network Block

is_internal_network if {
regex.match("^10\\..*", target)
}
is_internal_network if {
regex.match("^192\\.168\\..*", target)
}

allow if {
helpers.is_authenticated
is_allowed
not is_blocked
not is_internal_network
}

Next Steps