Skip to content

SDKs

Use Anthropic’s official Python, TypeScript and .NET SDKs to call your deployment’s Managed Agents API. The API uses the same request and response shapes as Anthropic’s Managed Agents API, so the SDKs work once you point them at your deployment. Some SDK methods aren’t supported and return 404 or 400. For the full list, see Coming from Anthropic’s API.

Install the SDK

The examples in these docs use the following SDK versions.

LanguagePackageVersion
Pythonanthropic1.17.0
TypeScript@anthropic-ai/sdk0.137.0
.NETAnthropic (NuGet)12.44.0
Python
pip install anthropic==1.17.0
TypeScript
npm install @anthropic-ai/sdk@0.137.0
.NET
dotnet add package Anthropic --version 12.44.0

The Python and TypeScript examples in the Quickstart and the playbooks run against a deployment. The cURL examples aren’t run. The other TypeScript examples compile with tsc --strict, and the other Python examples match the SDK’s signatures. The .NET SDK is tested against every response and event shape the API sends, with the SDK’s response checks on. For what differs in .NET, see .NET.

Set up the client

Set the base URL to your deployment’s address without a path, for example https://api.context.ai. The SDK adds /v1 itself. Pass your Task API key as the API key. To decide which key to create, see Choose a key.

Python
import os
from anthropic import Anthropic
client = Anthropic(
base_url=os.environ["CONTEXT_BASE_URL"], # for example https://api.context.ai
api_key=os.environ["CONTEXT_API_KEY"],
max_retries=0,
)
TypeScript
import Anthropic from "@anthropic-ai/sdk"
const client = new Anthropic({
baseURL: process.env.CONTEXT_BASE_URL, // for example https://api.context.ai
apiKey: process.env.CONTEXT_API_KEY,
maxRetries: 0,
})

Set max_retries to 0 in Python, maxRetries to 0 in TypeScript or MaxRetries to 0 in .NET. Sending events isn’t idempotent, so a retried send can deliver a message twice.

The endpoints are under client.beta: agents, environments, sessions, sessions.events, files and skills. Each endpoint’s reference page shows its SDK method.

Context headers

Some calls accept headers that are specific to Context. Pass them per call with extra_headers in Python or the headers request option in TypeScript. For example, a service account key can name the session’s owner with the x-context-owner-user-email header when it creates a session. Without the header, the key’s owner owns the session.

Python
session = client.beta.sessions.create(
agent="6f1c2a9e-0d4b-4c57-9a3e-2b7d8e1f4c60",
environment_id="env_default",
extra_headers={"x-context-owner-user-email": "member@example.com"},
)
TypeScript
const session = await client.beta.sessions.create(
{ agent: "6f1c2a9e-0d4b-4c57-9a3e-2b7d8e1f4c60", environment_id: "env_default" },
{ headers: { "x-context-owner-user-email": "member@example.com" } },
)

Pagination

When you loop over a list call, the SDK fetches each next page for you. limit sets the page size. It defaults to 20 and can be up to 100. For events, it defaults to 100 and can be up to 1,000. For skills, it can be up to 200.

Python
for session in client.beta.sessions.list(limit=100):
print(session.id)
TypeScript
for await (const session of client.beta.sessions.list({ limit: 100 })) console.log(session.id)

Streaming

Open the stream before you send an event, because the stream carries only events that happen after it opens. Stop reading at the first session.status_idle event whose stop_reason.type isn’t requires_action. A requires_action stop means the agent is waiting for you to approve or deny a tool call. To answer it, see the tool approvals playbook.

The SDKs don’t reconnect a dropped stream. To resume, reopen it with the Last-Event-ID header set to the ID of the last event you received. For how a stream ends and reconnects, see Stream events.

Each key can have 24 streams open on each server instance, unless your deployment sets another number. Opening another returns 429, so close each stream when you’re done with it.

Python
last_id = None
with client.beta.sessions.events.stream(session_id) as stream:
for event in stream:
last_id = event.id
if event.type == "session.status_idle" and event.stop_reason.type != "requires_action":
break
# After a dropped connection:
stream = client.beta.sessions.events.stream(session_id, extra_headers={"Last-Event-ID": last_id})
TypeScript
let lastId: string | undefined
const stream = await client.beta.sessions.events.stream(sessionId)
for await (const event of stream) {
if ("id" in event) lastId = event.id
if (event.type === "session.status_idle" && event.stop_reason.type !== "requires_action") break
}
// After a dropped connection:
const resumed = await client.beta.sessions.events.stream(sessionId, {}, { headers: { "Last-Event-ID": lastId! } })

Errors

An error response raises an exception in Python and throws one in TypeScript. The base class is APIStatusError in Python and APIError in TypeScript. Each status has its own subclass, such as NotFoundError for 404. The error body, including request_id, is in err.body in Python and err.error in TypeScript.

Python
import anthropic
try:
client.beta.sessions.retrieve("dd13d728-93e3-440a-874c-4efeb58c97e0")
except anthropic.APIStatusError as err:
print(err.status_code, err.body["error"]["message"], err.body["request_id"])
TypeScript
import Anthropic from "@anthropic-ai/sdk"
try {
await client.beta.sessions.retrieve("dd13d728-93e3-440a-874c-4efeb58c97e0")
} catch (err) {
if (err instanceof Anthropic.APIError) console.log(err.status, err.error) // err.error is the error body
}

.NET

Set BaseUrl to your deployment’s address without a path, ApiKey to your Task API key and MaxRetries to 0.

using Anthropic;
IAnthropicClient client = new AnthropicClient
{
BaseUrl = Environment.GetEnvironmentVariable("CONTEXT_BASE_URL")!, // for example https://api.context.ai
ApiKey = Environment.GetEnvironmentVariable("CONTEXT_API_KEY")!,
MaxRetries = 0,
};
var session = await client.Beta.Sessions.Create(new() { Agent = agentId, EnvironmentID = "env_default" });

The .NET SDK differs from the other two in a few places:

  • Uploads need a filename. Give the BinaryContent you upload a FileName. A bare byte[] sends no filename, and the upload returns 400.
  • Context headers go on a per-call client. In 12.44.0 the client’s own ExtraHeaders isn’t public. Add a header such as x-context-owner-user-email with client.WithOptions(o => o with { ExtraHeaders = ... }), and use that client only to create the session. Every other request refuses the owner header.
  • The stream skips session.usage. The SDK’s stream reader drops event names it doesn’t know, and session.usage is one of them. Read usage from the session (client.Beta.Sessions.Retrieve(id)) or from the event list.
  • Open the stream before you send. client.Beta.Sessions.Events.WithRawResponse.StreamStreaming(id) returns once the stream is open. StreamStreaming(id) sends its request only when you start reading.
  • The stream’s error frame raises AnthropicSseException, with ErrorType set to the error’s type.

See also

  • Coming from Anthropic’s API lists the calls that return 404 or 400, the headers that are ignored or refused and the limits that differ.
  • Stream events shows which frames the stream sends, how it ends and how to reconnect.