@steve-life/agent-sdk
v0.1.3
Published
Pure TypeScript SDK for routing normalized agent requests across configured agent and model nodes.
Downloads
524
Readme
Agent SDK
A pure TypeScript SDK for routing normalized agent requests across Codex SDK and Claude Agent SDK adapters.
The SDK is designed for applications that have many logical nodes and many backing agents. Client code owns the catalog, users can choose nodes and models at runtime, and the router handles fallback when a provider or local pool is at its limit.
Features
- TypeScript-first configuration with
codexAdapter(),claudeAgentAdapter(), andagentPool(). - User-selectable nodes and models through
router.listNodes(). - Logical agent pools: one node can contain multiple ordered backing agents.
- Automatic fallback on provider rate limits, quota/capacity errors, and local pool concurrency limits.
- Streaming events for text, provider raw events, usage, router fallback, router limits, and thinking/progress deltas.
- Direct
apiKeysupport from client code, with env-based config kept only as a compatibility path.
Install
npm install @steve-life/agent-sdkQuick Start
import {
agentPool,
claudeAgentAdapter,
codexAdapter,
createAgentRouter
} from "@steve-life/agent-sdk";
const router = createAgentRouter({
adapters: [
agentPool({
name: "planner",
displayName: "Planning Layer",
agents: [
codexAdapter({
name: "codex-primary",
models: ["gpt-5.3-codex", "gpt-5.3-codex-spark"],
apiKey: process.env.OPENAI_API_KEY,
thinkingLevel: "high"
}),
claudeAgentAdapter({
name: "claude-backup",
models: ["claude-sonnet"],
apiKey: process.env.ANTHROPIC_API_KEY
})
]
}),
codexAdapter({
name: "custom-codex",
displayName: "Custom Codex-Compatible",
models: ["custom-model-main", "custom-model-fast"],
baseUrl: "https://provider.example/v1",
apiKey: process.env.CUSTOM_PROVIDER_API_KEY
})
],
defaultAdapter: "planner",
fastAdapter: "custom-codex"
});
const result = await router.run({
prompt: "Review this repository and summarize the risky areas.",
cwd: process.cwd()
});
console.log(result.output);User Selection
Use listNodes() to render a node/model picker without exposing API keys.
const nodes = router.listNodes();
await router.run({
prompt: "Create a refactor plan.",
node: nodes[0].name,
model: nodes[0].allowedModels[0]
});agentPool() exposes one logical selectable node by default. Fallback agents are hidden from normal selection, but available for diagnostics:
const internalNodes = router.listNodes({ includeHidden: true });Streaming
runStream() emits the complete normalized router event stream. Use thinking.delta for model progress or reasoning summaries, text.delta for visible output, provider.raw when you need the underlying SDK event, and router.limit to show why the router moved to the next agent.
for await (const event of router.runStream({ prompt: "Plan the refactor" })) {
if (event.type === "thinking.delta") {
renderThinking(event.delta);
}
if (event.type === "text.delta") {
process.stdout.write(event.delta);
}
if (event.type === "router.limit") {
console.warn(`Switching from ${event.node}: ${event.limit.kind}`);
}
if (event.type === "provider.raw") {
debugProviderEvent(event.raw);
}
}For callback-style consumers, runWithHandlers() consumes the same stream and awaits each handler in event order. Handler failures reject the run. If the stream emits router.error, onError receives the normalized error payload before the original provider error is rethrown.
const result = await router.runWithHandlers(
{ prompt: "Plan the refactor" },
{
onThinkingDelta(delta) {
renderThinking(delta);
},
onTextDelta(delta) {
process.stdout.write(delta);
},
onRawEvent(raw) {
debugProviderEvent(raw);
},
onUsage(usage) {
updateTokenMeter(usage);
},
onError(error) {
reportStreamError(error);
}
}
);
console.log(result.output);Routing Rules
request.nodewins first.request.modelmust be allowed by the selected node.request.modelwithoutrequest.nodeselects the first node whose allowlist contains that model.- Fallback skips nodes that do not allow an explicit request model.
- A non-empty model allowlist must include the node's default model.
- Matching is exact string matching.
Providers
Only two provider kinds are public:
codex: backed by@openai/codex-sdkclaude-agent: backed by@anthropic-ai/claude-agent-sdk
Custom OpenAI-compatible endpoints should use codexAdapter({ baseUrl }). Custom Claude Agent endpoints should use claudeAgentAdapter({ baseUrl }); the SDK injects that value as ANTHROPIC_BASE_URL and passes the model allowlist as settings.availableModels.
Env Compatibility
TypeScript configuration is the recommended path. Env-defined nodes are still supported for older integrations, but they are not the best fit for systems with large dynamic node catalogs or user-selectable agents.
See .env.example for the compatibility format.
Development
npm install
npm run typecheck
npm test
npm pack --dry-runLicense
MIT
