Agent SDK Quickstart
Build a governed agent that enforces policies, correlates requests, and attributes costs — in under 5 minutes.
Prerequisites
- Node.js 20+
- A Keeptrusts gateway running (local via
kt gateway runor hosted) - An API token with
purpose=generalfor sending governed requests through the gateway - A bearer token for privileged control-plane reads (from console auth or
POST /v1/auth/login)
Step 1: Create the project
mkdir my-governed-agent && cd my-governed-agent
npm init -y
npm install @keeptrusts/agent typescript tsx
npx tsc --init --target ES2022 --module NodeNext --moduleResolution NodeNext
Step 2: Configure credentials
Create a .env file:
KEEPTRUSTS_GATEWAY_TOKEN=kt_live_your_gateway_request_token
KEEPTRUSTS_BEARER_TOKEN=your-control-plane-bearer-token
KEEPTRUSTS_GATEWAY_URL=http://localhost:41002/v1
KEEPTRUSTS_API_URL=https://api.keeptrusts.com
Use separate credentials here on purpose:
KEEPTRUSTS_GATEWAY_TOKENis the API token the agent runtime sends to the gatewayKEEPTRUSTS_BEARER_TOKENis the privileged server-side credential for event reads and agent registration
If you are also operating a hosted gateway, that gateway process may have its own KEEPTRUSTS_API_TOKEN with purpose=gateway_runtime. That runtime credential is separate from the app-side token used in this quickstart.
caution
Never commit .env to version control. Add it to .gitignore.
Step 3: Register the agent
Create src/register.ts:
import { registerAgent } from "@keeptrusts/agent";
import "dotenv/config";
async function main() {
const agent = await registerAgent({
bearerToken: process.env.KEEPTRUSTS_BEARER_TOKEN!,
apiUrl: process.env.KEEPTRUSTS_API_URL!,
name: "my-first-agent",
description: "Quickstart agent demonstrating governed inference",
});
console.log(`Agent registered: ${agent.id}`);
console.log(`Use this ID as your agentId: ${agent.id}`);
}
main();
Run it:
npx tsx src/register.ts
# → Agent registered: agt_abc123
Step 4: Build the agent
Create src/agent.ts:
import { createAgentRuntime } from "@keeptrusts/agent";
import "dotenv/config";
async function main() {
// Create the governed runtime
const agent = createAgentRuntime({
agentId: "agt_abc123", // from Step 3
gatewayUrl: process.env.KEEPTRUSTS_GATEWAY_URL!,
apiUrl: process.env.KEEPTRUSTS_API_URL!,
accessKey: process.env.KEEPTRUSTS_GATEWAY_TOKEN!,
bearerToken: process.env.KEEPTRUSTS_BEARER_TOKEN!,
});
// Send a governed request
const result = await agent.chat({
model: "gpt-5.4-mini-mini",
messages: [
{ role: "system", content: "You are a helpful code reviewer." },
{ role: "user", content: "Explain what OWASP Top 10 means." },
],
});
console.log("=== Response ===");
console.log(result.choices[0]?.message?.content);
// Read back what governance decided
console.log("\n=== Governance ===");
console.log(`Request ID: ${result.requestId}`);
console.log(`Agent ID: ${result.agentId}`);
const events = await agent.listEvents({ requestId: result.requestId });
if (events.length > 0) {
const event = events[0];
console.log(`Policy outcome: ${event.policy_outcome}`);
console.log(`Cost: ${event.event_cost_attribution?.total_cost}`);
}
}
main();
Step 5: Run the agent
npx tsx src/agent.ts
Expected output:
=== Response ===
OWASP Top 10 is a standard awareness document for web application security...
=== Governance ===
Request ID: 550e8400-e29b-41d4-a716-446655440000
Agent ID: agt_abc123
Policy outcome: allowed
Cost: 0.000245
What just happened
- Agent identity — the SDK attached
x-keeptrusts-agent-id: agt_abc123to the request - Request correlation — a unique
x-request-idwas generated and propagated - Distributed tracing — a
traceparentheader was created for end-to-end traces - Policy enforcement — the gateway evaluated all configured policies (input + output phases)
- Cost attribution — the decision event recorded exact token costs against your agent
- Event queryback — the SDK retrieved the event record using the same request ID
Step 6: Add streaming
const stream = await agent.chatStream({
model: "gpt-5.4-mini",
messages: [{ role: "user", content: "Write a haiku about governance." }],
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
console.log(`\n\nRequest ID: ${stream.requestId}`);
Streaming requests receive the same policy enforcement, identity, and correlation as non-streaming.
Step 7: Add evidence collection
const bundle = await agent.createEvidenceBundle({
requestId: result.requestId,
});
console.log(`Chain integrity: ${bundle.verification.chain_integrity}`);
console.log(`Public key kid: ${bundle.publicKey.kid}`);
console.log(`Digest: ${bundle.digest.storage_key}`);
What's next
| I want to... | Go to |
|---|---|
| See all capabilities | Capabilities |
| Configure for different environments | Configuration |
| Understand event flow | Observability |
| Produce audit-grade evidence | Evidence & Audit |
| Use MCP tools through the gateway | MCP Integration |
| Connect to Claude Code or Codex | Configuration → Adapters |