Skip to content

SDKs

The SDKs wrap the control plane’s REST API in typed methods, so you can start runs, hold sessions and script bulk operations from your own code instead of hand-writing HTTP. There are three: TypeScript (the fullest, and the only one that also writes agent code), Python (async, at management parity with Go) and Go. Pick your language in any tab; every tabbed example on the site follows it. For the raw endpoints see REST API.

SDK Package Import Notes
TypeScript @pal-runtime/sdk PalClient Event streams, retries, agent authoring (agent, step)
Python pal-runtime from pal import PalClient Async; runtime context (ctx.*) is stubbed
Go github.com/dshakes/pal/packages/sdk-go package pal Retries; no run event stream yet

Every sample here was checked against the SDK source on master (packages/sdk-ts, packages/sdk-python, packages/sdk-go).

Terminal window
# in your checkout
( cd packages/sdk-ts && npm install && npm run build )
# in your project: a file path, not the registry
npm install /path/to/checkout/packages/sdk-ts

All three read PAL_API_KEY and PAL_API_URL when you pass nothing. The built-in default URL is not a live service, so always set PAL_API_URL to your own control plane, for example http://localhost:8080.

import { PalClient } from "@pal-runtime/sdk";
const client = new PalClient({
apiKey: process.env.PAL_API_KEY,
baseUrl: process.env.PAL_API_URL ?? "http://localhost:8080",
});
import type { Run } from "@pal-runtime/sdk";
const run = (await client.runs.create({
agent: "research-agent",
input: { topic: "quantum computing" },
})) as Run;
// Live events until the run ends
for await (const event of client.runs.events(run.id)) {
console.log(event.kind, event.stepId, event.data);
}
const done = await client.runs.get(run.id);
console.log(done.status, done.output);
Event kinds you will see on the stream

step_started, step_completed, step_failed, tool_call, tool_result, llm_delta, log, approval, confidence_evaluated and end. The stream closes when the run is succeeded, failed or cancelled. See Token streaming.

const f = await client.runs.forecast({ agentName: "triage", input: "invoice is wrong" });
if (f.wouldExceedBudget) console.log("blocked:", f.blockReason);

A hard-fail budget then rejects the real run with HTTP 402.

const session = await client.sessions.create({ agent: "my-agent" });
for await (const chunk of client.sessions.streamMessage(session.id, {
content: "What is the capital of France?",
})) {
if (chunk.type === "delta") process.stdout.write(chunk.delta);
if (chunk.type === "completed") console.log("\nusage:", chunk.usage);
}
await client.sessions.delete(session.id);
import { PalApiError } from "@pal-runtime/sdk";
try {
await client.runs.create({ agent: "my-agent", input: {} });
} catch (err) {
if (err instanceof PalApiError && err.status === 402) {
// a hard-fail budget blocked the run
}
}

The TypeScript and Go clients retry HTTP 429, 503 and network errors with full-jitter backoff (TypeScript: 3 attempts, 500 ms base, 4 s cap; Go: WithMaxRetries). Other 4xx and 5xx are never retried.

client.agents // create, get, list, delete
client.runs // create, get, list, cancel, events, signal, forecast
client.sessions // create, get, list, sendMessage, streamMessage, events, stop, delete, close
client.connectors // list, get, execute, test, uninstall
client.budgets // upsert, get, list, delete
client.triggers // create, list, get, update, delete
client.evalSuites // upsert, list, get, delete
client.evalRuns // record, list
client.evalBaselines // set, get
client.experiments // create, list, get, recordOutcome, conclude
client.marketplace // list, get, publish, fork, star, unstar
client.mcp // listServers, getServer, attach, listAttachments, detach
client.receipts // issue, verify
client.feedback // submit, listForRun, summaryForAgent
client.rehearsals // pull
client.runtime // schedule, list, get, terminate, exec, execStream, pause, resume, fork, listFiles, readFile, writeFile

Sandbox VMs are covered in Sandbox lifecycle.

The SDKs above manage agents from outside. Inside an agent bundle, the TypeScript SDK gives you ctx: durable steps, LLM calls, tools, memory and connectors. Every step is journaled, so a crashed run resumes instead of restarting.

import { agent, step } from "@pal-runtime/sdk";
export default agent<{ query: string }>({
name: "my-agent",
model: "auto",
async run({ input, ctx }) {
// Durable step: journaled, idempotent, resumable after a crash
const data = await step("fetch-data", () => ctx.tools.web.search(input.query));
// Addressed by capability; PAL maps it to a vendor model
const summary = await step("summarize", () =>
ctx.llm.complete({
messages: [{ role: "user", content: `Summarize: ${data}` }],
capability: "reasoning-small",
}),
);
return { summary };
},
});
Parallel fan-out and human approval
// Fan out: one journaled step per query
const results = await step.map("search", queries, (q) => ctx.tools.web.search(q));
// Blocks until a human grants or denies; denial or timeout throws
await ctx.approval.request({
reason: "Send this email to 500 users?",
expiresAt: "2026-12-01T00:00:00Z",
});

Use capability names (auto, reasoning-large, chat-small, vision-large), never a vendor model. See Models.