Skip to Content
SDKsSDKs

SDKs

Keel’s first-class runtime SDKs are Python and TypeScript. They provide provider-shaped wrappers that send supported actions to Keel and typed clients for the public runtime API.

Go is published separately as an official generated/reference client for teams that want OpenAPI-derived bindings. It is not a first-class runtime wrapper SDK.

Install

pip install keel-sdk

Runtime wrapper migration

For Python and TypeScript, Keel keeps the provider-shaped calling pattern you already use. Change the import, set Keel environment variables, and the request is sent to Keel for authorization and execution.

# Before from openai import OpenAI # After from keel_sdk.providers.openai import OpenAI

Governance runs before provider dispatch. If Keel denies the request, the wrapper raises an explicit SDK error and no provider call is made.

Configure

export KEEL_BASE_URL="https://api.keelapi.com" export KEEL_API_KEY="keel_sk_your_project_key" export KEEL_PROJECT_ID="your-project-uuid"

Create a project, generate a project API key, add provider credentials, and set your first control in the Keel dashboard .

Provider API keys are stored in your Keel project. Python and TypeScript wrappers use your Keel credential for supported provider requests; they do not need the raw provider keys.

Working examples

from keel_sdk.providers.openai import OpenAI client = OpenAI() response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "Hello!"}], max_tokens=128, ) print(response["choices"][0]["message"]["content"])

Provider wrappers

Python and TypeScript expose wrappers for OpenAI, Anthropic, Google Gemini, xAI, and Meta. Use Provider Support and the Capability Matrix for the current provider and operation surface.

Advanced operations such as image generation, audio, embeddings, and search evidence are route-dependent. Provider-native tool runs are not a governed Keel surface, and the managed routes refuse requests that carry tool definitions. Use /v1/executions, /v1/execute, or the direct SDK client when the wrapper surface is not the right fit.

Direct client access

Use the direct client when you need precise control over permits, executions, proxy calls, jobs, compliance exports, governance events, integrity endpoints, MCP evidence, metrics, status, or webhooks.

TypeScript

import { KeelClient } from "keel-sdk"; const client = new KeelClient({ baseUrl: process.env.KEEL_BASE_URL!, apiKey: process.env.KEEL_API_KEY!, }); const permit = await client.permits.create({ project_id: process.env.KEEL_PROJECT_ID!, idempotency_key: "permit-only-001", subject: { type: "user", id: "usr_123" }, action: { name: "ai.generate" }, resource: { type: "request", id: "req_123", attributes: { provider: "openai", model: "gpt-4o-mini", operation: "generate.text", estimated_input_tokens: 120, estimated_output_tokens: 80, max_output_tokens_requested: 120 } } });

Python

from keel_sdk import KeelClient client = KeelClient( base_url="https://api.keelapi.com", api_key="keel_sk_...", ) permit = client.permits.create({ "project_id": "your-project-uuid", "idempotency_key": "permit-only-001", "subject": {"type": "user", "id": "usr_123"}, "action": {"name": "ai.generate"}, "resource": { "type": "request", "id": "req_123", "attributes": { "provider": "openai", "model": "gpt-4o-mini", "operation": "generate.text", "estimated_input_tokens": 120, "estimated_output_tokens": 80, }, }, })

Go reference client

The Go package is an official generated/reference client. It does not maintain provider-specific wrappers, streaming helpers, custom retry policy, or custom error types.

import keelclient "github.com/keelapi/keel-go/pkg/keelclient"

Runtime API calls should use pkg/keelclient. The repository root package is documentation-only.

The generated client adds no authentication or freshness headers. Register a request editor that sets the project key and, on every request, a current X-Keel-Timestamp and a new X-Keel-Nonce; hosted Keel rejects permit, execution, and proxy requests without them (401 request_not_fresh).

client, err := keelclient.NewClient( os.Getenv("KEEL_BASE_URL"), keelclient.WithRequestEditorFn(func(ctx context.Context, req *http.Request) error { nonce := make([]byte, 16) if _, err := rand.Read(nonce); err != nil { // crypto/rand return err } req.Header.Set("Authorization", "Bearer "+os.Getenv("KEEL_API_KEY")) req.Header.Set("X-Keel-Timestamp", strconv.FormatInt(time.Now().Unix(), 10)) req.Header.Set("X-Keel-Nonce", hex.EncodeToString(nonce)) return nil }), ) if err != nil { log.Fatal(err) }

See Go Reference Client for a complete, compilable permit example.

Generated Go clients return standard *http.Response values. Callers own status handling, decoding, retry policy, and transport configuration.

Error handling

When governance blocks a wrapper request, Python and TypeScript raise KeelError before any provider call is made.

import { KeelError } from "keel-sdk"; try { await client.chat.completions.create({ model: "gpt-4o", messages: [{ role: "user", content: "Hello!" }], }); } catch (err) { if (err instanceof KeelError) { console.error(`Keel error ${err.status}: [${err.code}] ${err.message}`); } }

Common cases:

  • HTTP 403 with the policy reason code (for example policy.rule_denied) when project policy denies the request.
  • HTTP 403 attestation_required when the request is held for human review.
  • HTTP 429 budget.rate_limit_throttled when budget or rate-limit controls throttle.
  • A Keel refusal returned with a 5xx status, such as pricing_not_configured, is raised as-is: the SDK does not retry a refusal that a retry cannot change.
  • upstream provider failures after an allow decision, surfaced through the wrapper or proxy response.

Where to go next

Last updated on Edit this page on GitHub