Ship the agent. Keep the pager quiet.
A TypeScript agent SDK for teams putting an agent in front of real users. Define an agent, add tools, run a loop that cannot hang, get a typed result — with the production problems already solved, and nothing in your dependency tree.
$pnpm add just-another-sdkWhy another one
The demo is the easy half. The bill, the breach, and the outage are the other one.
Every agent framework demos beautifully. Then you put one in front of real users, and the interesting problems turn out to be the unglamorous ones: a model that loops until your bill spikes, a tool exception that takes down a request, an API key that ends up in a CI log, a filesystem tool that reads one directory too far, a vendor outage with no second path, and no way to see what your agent actually did.
just-another-sdk treats those as the product, not the appendix. Every one of them is a default, a type, or a test — not something you remember to add on the Friday before launch.
Not adjectives
Every claim on this page is something you can run.
Real output, copied from actual runs in the repository. All three run offline, with no API key at all.
A vendor goes down. The run does not.
Anthropic returns 529. The retry policy backs off, gives up, and the same run continues on the next provider — one run id, one usage total, one transcript. Failing over is a line in your trace instead of a page in your incident channel.
The whole API
Four concepts. No ceremony.
An Agent is immutable configuration, so one instance safely serves every concurrent request. Run state is separate; sessions are separate again. Tools are plain functions with a schema — any Standard Schema validator, so Zod is your choice and never our dependency.
- Agent
- immutable config: model, tools, handoffs, policy
- tool()
- schema in, typed handler out
- RunResult
- output, steps, usage, agentPath
- ModelProvider
- one method: generate()
import { Agent } from 'just-another-sdk'
import { anthropic, google } from 'just-another-sdk/providers'
import { webTools } from 'just-another-sdk/tools'
const support = new Agent({
name: 'support',
instructions: 'Help the customer. Use your tools.',
// Native Claude. If Anthropic is having a day,
// the same run continues on Gemini.
model: anthropic('claude-opus-5'),
fallbacks: [google('gemini-2.5-pro')],
tools: [...webTools(), issueRefund],
// A person approves anything that moves money.
toolGuardrails: [
{
name: 'confirm-refunds',
tools: ['issue_refund'],
check: () => ({ requireApproval: true }),
},
],
// Escalate to a specialist when it needs one.
handoffs: [billing, technical],
})
const result = await support.run(message, { sessionId: userId })
result.output // the answer, typed
result.agentPath // ['support', 'billing']
result.usage // { inputTokens: 412, … }Three vendors, natively. The rest for free.
Claude speaks the Messages API, Gemini speaks generateContent, and OpenAI speaks Chat Completions — each a direct fetch call, not a vendor SDK. OpenRouter reaches hundreds more through one key, and the same compatible transport covers anything that speaks the OpenAI shape. Writing your own means implementing one method.
■native transport · ■ OpenAI-compatible
Running in about two minutes.
Runnable examples ship with the repository, and several of them need no API key.
$pnpm add just-another-sdk