Claude Agent SDK: using the VIDAI Control Plane as the backend¶
The Claude Agent SDK constructs an Anthropic client under the
hood. Pass base_url= when you initialise the SDK's client (or
set the equivalent env vars) and every agent turn, tool call,
and long-running task routes through the control plane.
TL;DR¶
export ANTHROPIC_BASE_URL=https://your-vidai-server.example.com
export ANTHROPIC_API_KEY=your-vidai-key
Prerequisites¶
pip install claude-agent-sdk.- Control plane base URL and an API key from API Keys.
- A Claude-family model registered on the Models page.
Note: the Anthropic client wants the root base URL (no /v1);
it appends /v1/messages itself. That's what the control plane
serves on the Anthropic wire path.
Passing config explicitly¶
from anthropic import AsyncAnthropic
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
client = AsyncAnthropic(
base_url="https://your-vidai-server.example.com",
api_key="your-vidai-key",
)
async with ClaudeSDKClient(
options=ClaudeAgentOptions(client=client),
) as agent:
await agent.query("reply with: ok")
async for msg in agent.receive_response():
print(msg)
Tools¶
Custom tools defined with @tool are called through the same
client. Every tool round-trip is a control-plane request that
lands in Request Logs:
from claude_agent_sdk import tool
@tool("get_weather", "Get current weather", {"city": str})
async def get_weather(args):
return {"content": [{"type": "text", "text": f"Sunny in {args['city']}."}]}
Multi-turn conversation¶
The SDK's ClaudeSDKClient holds a conversation across calls;
each turn is a control-plane request:
async with ClaudeSDKClient() as agent:
await agent.query("Draft a launch checklist.")
async for msg in agent.receive_response(): print(msg)
await agent.query("Now critique it.")
async for msg in agent.receive_response(): print(msg)
Streaming¶
The SDK's receive_response() is streaming by default. No extra
config needed — the control plane forwards the stream from the
Claude upstream unchanged.
Cross-provider routing¶
Even though the SDK is Claude-branded, a model registered on the
control plane that routes to a non-Claude upstream is callable
by name. The control plane translates the Anthropic-shape
request into the upstream's wire format. From the SDK's point
of view it's still calling /v1/messages and getting the
response shape it expects.
Verify it works¶
import asyncio
from claude_agent_sdk import query
async def main():
async for message in query("reply with exactly: ok"):
print(message)
asyncio.run(main())
A row appears on Request Logs within a few seconds.
If something's off¶
Raise an issue at github.com/vidaiUK/vidai-quickstart/issues with your SDK setup and the query that reproduces the issue. We'll get it sorted.