Client libraries for the AgentContextOS gateway, in five languages. This page is the public reference (install + usage) and the technical reference (generation pipeline + status) for all of them.
| SDK | Package | Path | Status |
|---|---|---|---|
| Python | agentcontextos |
sdks/python |
hand-written, tested |
| TypeScript | @agentcontextos/sdk |
sdks/typescript |
hand-written, tested |
| Go | agentcontextos |
sdks/go |
generated |
| Java | com.agentcontextos:agentcontextos-sdk |
sdks/java |
generated |
| .NET | AgentContextOS.Sdk |
sdks/dotnet |
generated |
All five are produced from two contracts:
- REST — the OpenAPI 3.1 spec at
dist/openapi.json(covers/v1/query,/v1/retrieve,/v1/corpora,/v1/ingest/document,/v1/embeddings,/v1/chat/completions,/v1/models,/v1/agent). - gRPC —
proto/rag.proto'sRagService.
Every SDK applies identity the way each route expects, so callers configure it once:
- Body identity —
/v1/query,/v1/retrieve,/v1/agentcarrytenant_id/principal_idin the request body. - Header identity —
/v1/corpora,/v1/embeddings,/v1/chat/completions,/v1/modelsreadAuthorization: Bearer <token>(production) orX-Tenant-Id/X-Principal-Id(dev) headers.
Configure tenant_id + principal_id for the dev/demo path, or api_key
(+ tenant_id) for production. The SDK sends the bearer token in preference to
the dev X-Principal-Id header when an api_key is set.
from agentcontextos import Client, AsyncClient
with Client("http://localhost:8000", tenant_id="acme", principal_id="svc") as rag:
hits = rag.retrieve("How do I rotate signing keys?", top_k=5)
resp = rag.query("How do I rotate signing keys?", generate=True)
chat = rag.chat([{"role": "user", "content": "Summarise the policy"}])
for chunk in rag.stream_chat([{"role": "user", "content": "Explain HNSW"}]):
print(chunk.choices[0].delta.content or "", end="")
result = rag.agent("Find and summarise the on-call runbook")
async with AsyncClient(url, tenant_id="acme", principal_id="svc") as rag:
resp = await rag.query("...")
async for ev in rag.stream_agent("..."):
print(ev.kind, ev.phase)Errors raise an ApiError subclass keyed by status (BadRequestError,
AuthenticationError, PermissionDeniedError, NotFoundError,
RateLimitError, ServerError), each carrying .code, .message,
.request_id. A failed agent run raises AgentRunError. Wire models are
re-exported from agentcontextos.models.
import { AgentContextOSClient } from '@agentcontextos/sdk';
const rag = new AgentContextOSClient('http://localhost:8000', {
tenantId: 'acme',
principalId: 'svc',
});
const resp = await rag.query('How do I rotate signing keys?', { generate: true });
for await (const chunk of rag.streamChat([{ role: 'user', content: 'hi' }])) {
process.stdout.write(chunk.choices[0]?.delta.content ?? '');
}
const result = await rag.agent('Find the on-call runbook');Works in Node 18+ and browsers (platform fetch + ReadableStream, no runtime
dependency). Errors reject with the same ApiError subclasses.
These are generated on demand (see below). After task sdk:gen, import the
generated client from each SDK's package; the operation set mirrors the REST
routes, and identity follows the same model. See each SDK's README:
Go, Java,
.NET.
dist/openapi.json ──(openapi-generator-cli)──▶ sdks/{go,java,dotnet}/generated/ (REST client)
proto/rag.proto ──(buf generate)───────────▶ sdks/{go,java,dotnet}/.../gen (gRPC stubs)
Commands (repo root):
task openapi:gen # re-export dist/openapi.{json,yaml} from the live app
task openapi:check-drift # CI gate: fail if the committed spec is stale
task sdk:gen # both halves, all generated languages
task sdk:gen-proto # gRPC stubs only (needs buf)
task sdk:gen-openapi # REST clients only (needs openapi-generator-cli + a JRE)scripts/export_openapi.py runs build_app().openapi() with default noop SPIs
(no infrastructure) and writes a byte-stable, sorted spec.
scripts/gen_sdks.py orchestrates buf + openapi-generator-cli, detects a
missing toolchain and prints an install hint (skip by default, --strict to
fail). The generator version is pinned in openapitools.json.
See ADR-0016. In short: Python and TypeScript are hand-written flagships (idiomatic ergonomics, full streaming, tested against a live gateway); Go/Java/.NET are generated to keep marginal maintenance near zero. The committed spec is drift-gated; the generated SDK source is a gitignored build artifact.
- Add a generated language — add its
openapi-generatorgenerator name toOPENAPI_GENERATORSinscripts/gen_sdks.py, abuf.gen.yamlplugin block, ansdks/<lang>/openapi-generator-config.yaml, and a scaffold README +.gitignore. - Evolve the REST surface — the spec is auto-derived from FastAPI routes +
rag_coremodels; runtask openapi:genand commit. Regenerate the SDKs withtask sdk:gen. - Evolve the hand-written SDKs — request builders live in
agentcontextos._core(Python) /client.ts(TS); add a method per new route and a test against the in-process gateway (Python) / afetchstub (TS).
- architecture/sdk-generation.md — pipeline design + drift gate.
- guides/sdk-quickstart.md — 5-minute tour.
- ADR-0016 — the decision.
- reference/gateway.md / reference/grpc.md — the surfaces the SDKs wrap.