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
Python
pip install keel-sdkRuntime 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.
Python
# Before
from openai import OpenAI
# After
from keel_sdk.providers.openai import OpenAIGovernance 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
Python
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_requiredwhen the request is held for human review. - HTTP 429
budget.rate_limit_throttledwhen 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
- Python — Python runtime SDK
- TypeScript — TypeScript runtime SDK
- Go — generated/reference client
- SDK Support Surfaces — official support posture
- Provider Support — provider caveats
- Capability Matrix — operation coverage
- Terraform — infrastructure management