unlob Docs
Browse documentation

Claude Agent SDK

unlob as an MCP server beside the SDK's own file and shell tools.

What you are installing

The Claude Agent SDK is Claude Code packaged as a library. One query() call gets you the whole harness: the agent loop, context compaction, permissions, subagents, and built-in Read / Write / Edit / Bash / Grep tools.

It is a different package from the Tool Runner in the anthropic SDK, and the two are easy to confuse. The Tool Runner loops over tools you define and ships none of its own; the Agent SDK ships the tools. Reach for the Agent SDK when the agent needs the filesystem and the shell as well as the web. When it only needs a few tools you wrote, the Tool Runner is a much smaller dependency — see Tool use, directly.

pip install claude-agent-sdk

Add unlob as an MCP server

import os
from claude_agent_sdk import query, ClaudeAgentOptions

options = ClaudeAgentOptions(
    mcp_servers={
        "unlob": {
            "type": "http",
            "url": "https://api.unlob.com/mcp",
            "headers": {"x-api-key": os.environ["UNLOB_API_KEY"]},
        }
    },
    system_prompt=(
        "Search with unlob before answering questions about the world. Use "
        "assemble_context for open questions and web_search for specific ones. "
        "Call corroborate before stating anything as established fact, and say how "
        "many independent sources carry it."
    ),
)

async for message in query(
    prompt="What changed in the EU AI Act GPAI rules this year? Write it to notes.md.",
    options=options,
):
    print(message)

The eleven unlob tools arrive alongside the SDK’s built-in ones, so that prompt does research and file-writing in one run without you wiring anything between them.

Restrict the tool surface

The SDK’s built-in tools plus eleven of ours is a lot of schema, and Bash in particular is worth withholding unless the task needs it:

options = ClaudeAgentOptions(
    mcp_servers={"unlob": {...}},
    allowed_tools=[
        "Read", "Write", "Grep",
        "mcp__unlob__web_search",
        "mcp__unlob__corroborate",
        "mcp__unlob__assemble_context",
    ],
)

MCP tools are namespaced mcp__<server>__<tool>. Getting that prefix wrong is silent: the allowlist matches nothing, and the agent reports that it has no search tool.

Subagents

Research fans out well. A subagent that reads sources and returns a summary keeps the main agent’s context clear of everything it read to get there:

options = ClaudeAgentOptions(
    mcp_servers={"unlob": {...}},
    agents={
        "researcher": {
            "description": "Researches one question against the web and returns a "
                           "cited summary. Use for anything needing sources.",
            "prompt": "Search with unlob. Corroborate before asserting. Cite URLs.",
            "tools": ["mcp__unlob__web_search", "mcp__unlob__corroborate"],
        }
    },
)

This is where assemble_context earns its place: one call returns a packed, trust-ranked reading set, so a subagent spends its context on the answer rather than on the retrieval loop that found it.

Worth knowing

  • The key goes in headers, not in the URL. It is read per request; there is no login step.
  • Refusals from unlob — a suspended account, an exhausted quota — arrive as tool errors inside the turn, not as exceptions. Your try/except will not see them; the agent will read them and should report them.
  • A search result with partial: true means part of the corpus was unreachable. Tell the agent to say so rather than reporting a short answer as a complete one.

Next