Repository navigation
Releases
v0.14.5: super on budget checks
A replaced budget check can now call the default as super, and a run always stops at its cap even when its budget event fails to send. Go module github.com/eadwinCode/agentic-kit/packages/go-agentenkit@v0.14.5, npm agentenkit@0.14.5 and use-agentenkit@0.14.5.
No breaking changes for checks the loop builds. A check object you build by hand to pass to your own hook must now set super (Go: Super).
New: super on budget checks (#46)
TS: c.super(c). Go: c.Super(ctx, c).
- It is the default check: the token cap or the money cap. Call it to keep the cap and add your own rule on top.
- When it returns true it has already sent
TOKEN_BUDGET_EXHAUSTEDorCOST_BUDGET_EXHAUSTED. Don't send it again. - The TS defaults (
defaultCheckTokenBudgetExhausted,defaultCheckCostBudgetExhausted) still take a check withoutsuper, so calling them directly still compiles.
Fixed (#47)
- A budget event that fails to send no longer lets a run go past its cap. In TS, a failed send inside the default check threw, and the loop read that as "don't stop". Go ignored the error and stopped. The
publisha check gets now logs a failure and never throws (Go: returns nil), so both runtimes stop.
Docs
- The package READMEs and Multi-tenancy point to the budget check hooks. Multi-tenancy says to refuse an empty balance in
billingPreCheck, since the first step of a segment runs before any check.
v0.14.0: budget checks you can replace
The two budget checks the loop runs after every step can now be replaced, in both runtimes. A host can stop a run on its own rule, such as a live balance that other runs spend at the same time. Go module github.com/eadwinCode/agentic-kit/packages/go-agentenkit@v0.14.0, npm agentenkit@0.14.0 and use-agentenkit@0.14.0.
No breaking changes.
New: your own budget checks (#44)
Go: RuntimeOptions.CheckTokenBudgetExhausted and CheckCostBudgetExhausted. TS: checkTokenBudgetExhausted and checkCostBudgetExhausted on setupAgentCore.
- The defaults are the old token cap and money cap, exported as
DefaultCheckTokenBudgetExhausted/DefaultCheckCostBudgetExhausted(TS:defaultCheck…Exhausted), so a hook can call them and keep the cap. - A check is told the run (
runId,threadId,agentId,state), the step that just finished (step, the stored step record), whether another step would follow (willContinue), what the run has spent with its cap, andpublish. - True ends the run before the next step, with
stopReasontoken_budgetorcost_budget. The check says why withpublish; the defaults still sendTOKEN_BUDGET_EXHAUSTEDandCOST_BUDGET_EXHAUSTED. - A check that fails (TS: throws; Go: returns an error or panics) is logged and read as false. To fail closed, handle your own errors and return true.
- Nested runs are checked against their parent's run id, and may call the check at the same time as their parent.
- The first step of a segment runs without a check. Refuse a run on an empty balance in
billingPreCheckat pickup.
Changed
stopReason: 'token_budget'now comes from the token check's answer, not from a sum at finalize. With the default check, nothing changes.
v0.13.0: per-tool time limit
A time limit per tool, in both runtimes: one slow tool can get more time while StepTimeout stays short for every other step. Go module github.com/eadwinCode/agentic-kit/packages/go-agentenkit@v0.13.0, npm agentenkit@0.13.0 and use-agentenkit@0.13.0.
No breaking changes.
New: a tool's own time limit (#42)
Go: Tool.Timeout, or agentenkit.WithToolTimeout(t, 30*time.Minute). TS: withToolTimeout(tool, ms), which returns a copy of the tool.
- While a call runs, its step has at least that long, even when
StepTimeout(TS:stepTimeoutMs) is shorter. Once the call returns, the step is back toStepTimeout, counted from then. - A call past its own limit ends the step like a step past
StepTimeout: the samestep N ran longer than …error, naming the limit that ran out, and the same retry. - Other tools keep the step limit. A tool in the same step as a slow one shares its longer time.
- The tool must stop when its
ctxis done (TS: when itsabortSignalfires), as with the step limit. - It does not lift
SegmentTimeout, or a queue's own job limit, such as Flow's step time. Keep those longer than your slowest tool.
New: a subagent's own time limit (#42)
Go: SubagentsConfig.Timeout. TS: subagents.timeoutMs. A child's whole run happens inside one spawnSubagent call, so inside one step of the parent. This gives that call its own limit, so a child, and a slow tool inside it, can outlast the parent's StepTimeout.
Changed
- Go: a step whose tools include a timed tool now has a context with no
Deadline(), because a deadline cannot be moved later. When time runs out,ctx.Err()isCanceledandcontext.CausesaysDeadlineExceeded. The timed call itself gets a real deadline. Steps with no timed tool are as before. - Go: a timed-out step keeps the provider's own error text, for example
context deadline exceeded (stream read: context canceled). TS keeps it as the error'scause. - TS: a step whose time runs out just as the model finishes now fails and retries, as in Go.
v0.12.0
Operator tools and limits for queues, in both runtimes: a shared QueueAdmin port, and FlowQueue gets it plus new options. Go module github.com/eadwinCode/agentic-kit/packages/go-agentenkit@v0.12.0, npm agentenkit@0.12.0 and use-agentenkit@0.12.0.
No breaking changes.
New: QueueAdmin port (#40)
pause, resume, purge, listDead, redrive and purgeDead (Go: Pause, Resume, Purge, ListDead, Redrive, PurgeDead). The Go Postgres queue and FlowQueue both have it, so admin code works with either. The Go Postgres PurgeFilter and DeadJob now point to the shared ports types, so existing code still compiles.
On FlowQueue:
pausepauses the Flow function. Jobs enqueued meanwhile wait and start onresume.- A dead job is a failed run.
redriveretries it, but never a run thatpurgecancelled.purgecancels waiting runs that match. Running ones are left alone, and an empty filter is refused.purgeDeaddeletes failed runs, except ones kept in the dashboard.
New: FlowQueue options (#40)
maxDepth(Go:MaxDepth) refuses a fresh dispatch withQueueFullError. The count lags a few seconds.namespace(Go:Namespace) goes in front of the function ID, so two environments can share one Flow app.statsasks Flow for the oldest queued job, sooldestReadyMsno longer reads low.
New: agentRunFunction options (#40)
Go: clevixflow.Functions.
globalConcurrencylimits all jobs at once, beside the per-partitionKeylimit.retryBackoffMsandretryBackoffMaxMs(Go:RetryBackoff,RetryBackoffMax) set the wait between tries, as on the Postgres queue.segmentTimeoutMs(Go:SegmentTimeout) throws if a segment is not shorter than the step time.
Needs: Flow SDK v0.8.0 (TS: @clevix/flow, from the flow-sdk release), and Flow engine v2.2.0 or newer.
See Setup: On Clevix Flow, with a new note on rollouts, and QueueAdmin.
v0.11.0: Clevix Flow adapters
agentic-kit can now run on Clevix Flow: the queue, the bus and the run streams. Go module github.com/eadwinCode/agentic-kit/packages/go-agentenkit@v0.11.0, npm agentenkit@0.11.0 and use-agentenkit@0.11.0.
Breaking (Go only)
- Go 1.27 or newer. flow-sdk needs it, so go-agentenkit does too.
The TS packages have no breaking changes.
New: Clevix Flow adapters (#38, both runtimes)
TS: agentenkit/adapters/flow. Go: adapters/clevixflow.
FlowQueue(Go:clevixflow.New), theQueueport. Each job is a Flow run that you can watch in the Flow dashboard.- A job key is the run's singleton key, so a key that a live run holds throws
DuplicateJobError. - A delay is a sleep inside the run. Priority becomes Flow's run priority.
cancel,findandstatsuse Flow's runs API.findandstatslag by a few seconds.
- A job key is the run's singleton key, so a key that a live run holds throws
agentRunFunction(Go:clevixflow.Functions) makes the Flow function that runs the jobs. Serve it with Flow'sserve. When Flow gives up on a run, the job goes tohandleDeadJob.FlowBus(Go:clevixflow.NewBus), theEventBusport. One Flow realtime channel per thread, and one socket per thread per process. Big events go through the kv.FlowStreams(Go:clevixflow.NewStreams), theRunStreamsport, on Flow streams. Appends go in batches, and big items go through the kv. Time to live and grace are capped at Flow's 7 days.
The bus and the streams need a Kv. You can use any mix: for example FlowQueue with the Redis bus.
Needs: Flow SDK v0.7.0 (TS: @clevix/flow, an optional peer dependency, installed from the flow-sdk release), and Flow engine v2.1.1 or newer.
Limit: a Flow stream holds at most 20,000 items, and an append past that fails. Keep segments short.
See Setup: On Clevix Flow and the examples flow-queue-ts and flow-queue-go.
Other
- A Go
web_fetchtest that failed about 1 run in 3 is fixed.
v0.10.0: AI SDK 7 and run sandboxes
AI SDK 7, sandboxes per run, and the TypeScript package catching up with Go. Go module github.com/eadwinCode/agentic-kit/packages/go-agentenkit@v0.10.0, npm agentenkit@0.10.0 and use-agentenkit@0.10.0.
Why 0.10.0: the Go module had its own releases after 0.7.0 (v0.8.0–v0.9.0). From now on the Go module and the npm packages share one version number. npm skips 0.8 and 0.9.
Breaking (TS only)
- AI SDK 7 (#34).
aiis now a peer dependency (^7.0.0): install it next to agentenkit,bun add agentenkit ai zod. Node 22 or newer is needed. agentTool({ parameters })is nowagentTool({ inputSchema }), like the SDK's owntool().- The examples use
@ai-sdk/openai4 and callopenai.chat(...)to stay on Chat Completions.
The stored messages and the streamed chunks do not change shape, so existing threads keep loading and clients need no change.
New: run sandboxes (#35, both runtimes)
sandboxScope: 'run'(Go:SandboxScope: agentenkit.SandboxScopeRun): each run gets its own sandbox. It is ended when the run finishes, fails, is stopped or parks;sandboxKeepOnParkkeeps it through a park. The default stays one sandbox per thread.- A provider can restore the work folder (TS:
restoresWorkdir: true; Go: theWorkdirRestorerinterface). The tools then tell the model the project files are back, not gone. sandboxDefaults: network, envs, template, image, resources and extra for every sandbox the runtime makes.sandboxStateDir: where the sandbox tools keep their own files. An absolute path keeps.agentenkitout of the work folder, with a folder per sandbox.afterSandboxCall(Go:Tools.AfterSandboxCall): called once after each tool call that used the sandbox, for example to save the work. Its error reaches the model as the call's error.
See Sandboxes.
New in TS, as Go already had (#36)
- A prompt refused as too long no longer fails the run. The thread is compacted at once and the run goes on from its saved steps.
runtime.compactThread(threadId, state)compacts on request, for a/compactcommand. - A history larger than the summary model is summarized in parts, then merged.
- The settle hook gets the run's state as
info.runState, also when the sweep retries it later.
Fixed
- A rate limit worded "too many tokens" (AWS Bedrock) is no longer mistaken for a too-long prompt (both runtimes).
- After a too-long retry, a run's token count includes the steps before the refusal (both runtimes).
Other
web_fetchcan be limited to links from searches or from the user (OnlyKnownURLs, #32).
v0.7.0: prune per tenant
PruneEvents can now prune one tenant's events, so a storage that keeps a database per tenant can clear the old stream-only rows. Go module github.com/eadwinCode/agentic-kit/packages/go-agentenkit@v0.7.0, npm agentenkit@0.7.0 and use-agentenkit@0.7.0.
Changed (#26)
- New option:
PruneOptions.State(TS:runtime.pruneEvents({ state })) reaches the storage the same way a run's state does. Run it once per tenant. With no state, it works as before. - Where it applies:
runtime.pruneEventsandAgentCore.PruneEventsapply it. The low-levelpruneEvents(deps)andcore.PruneEventsprune with the statedepsis bound with.
Breaking (Go only)
EventPruner.Prunetakes a trailingsc ports.StorageContext, like every other storage method. A custom adapter that prunes has to add it. The kit's memory, SQLite and Postgres adapters are updated.BoundEvents.Pruner()returns a*ports.BoundPruner, with the context already attached, instead of anEventPruner.
TS has no breaking changes. The optional events.prune port now declares the ctx argument the bound storage was already passing.
v0.6.1: stopped runs are billed in full
A fix for the Go runtime. Go module github.com/eadwinCode/agentic-kit/packages/go-agentenkit@v0.6.1, npm agentenkit@0.6.1 and use-agentenkit@0.6.1.
No breaking changes.
Fixed (#24)
- Before: a stop that landed after the provider answered, but before the call was priced, could make a pricer that reads a price list fail with
context canceled. The paid call was then stored unpriced, so it was never billed. - Now: Go prices a usage row on a context a stop cannot cancel, as it already did for the write.
- Covered: every call: steps of the main run and nested runs, compaction passes and tool calls.
- TS: already behaved this way. Its pricer is never given a signal.
v0.6.0: MCP tools
Agents can use tools from MCP servers, plus fixes found while moving Clevix to the latest kit. Go module github.com/eadwinCode/agentic-kit/packages/go-agentenkit@v0.6.0, npm agentenkit@0.6.0 and use-agentenkit@0.6.0.
No breaking changes.
MCP tools (#21)
- A small MCP client in both runtimes:
agentenkit/adapters/mcpandgo-agentenkit/adapters/mcp. It needs no new dependencies. - It connects over stdio or streamable HTTP and turns each of the server's tools into an ordinary tool.
- Options: a name prefix, a list of tools to keep, approval per tool, and a time limit.
- Tool errors, time limits and a lost server go back to the model as
{"error": ...}. - See the new MCP docs page.
Fixes (#22)
- Refused sends no longer grow the thread. A send refused at dispatch (billing, a full queue) is now sent live only, so a user who keeps pressing Send no longer adds a row to the thread each time. A refusal at pickup belongs to a run and is still stored.
- Admin reads can carry the tenant.
rt.Admin.WithState(state)(TS:runtime.admin.withState(state)) lets the reads that go to storage carry the tenant. These are a run's and a thread's spend, and a run's events. - use-agentenkit:
- A refused
run()returnsreasonandretryAfterSeconds, from the body or aRetry-Afterheader. - It reads
{ error: { code, message } }bodies. - After a reload, a tool call carries its stored
result. isToolErrorreads JSON text and lists of results.isToolParkedandtoolCallResultsare exported.
- A refused
isToolUse/IsToolUsetell a paid tool service's usage line from a model call.
v0.5.0: built-in tools
Built-in tools that any model can use, in both runtimes: web search and web fetch, and bash, code_execution and text_editor in one sandbox per thread. Go module github.com/eadwinCode/agentic-kit/packages/go-agentenkit@v0.5.0, npm agentenkit@0.5.0 and use-agentenkit@0.5.0.
No breaking changes: everything new is opt-in.
Built-in tools
runtime.builtinTools([...])(Go:rt.BuiltinTools) gives an agent tools with one name and one input shape in every runtime. The shared definitions live inpackages/parity/tools/.- The adapters behind them are passed in at setup, with their keys:
setupAgentCore({ tools: { search, fetcher, sandbox } })(Go:RuntimeOptions.Tools). Nothing reads the environment later. - Each tool call writes a usage row (
kind: 'tool'), so tool spend counts against a run's money cap.pricing.toolsprices it per use, and now per second too.
Web tools
web_search: short result ids (s1r2), a limit on uses per run, and domain lists and recency set by the app, not the model. Adapters:BraveWebSearch,JinaWebSearch.web_fetch: reads a page by URL or result id. With aprompt, a small model answers from the page, so a long page never fills the context. Adapters: our ownPageReader(free, refuses private addresses) andJinaReader.- A URL sent with an unknown id is read, rather than failing.
Sandboxes
- A new sandbox port, shaped like ComputeSDK's. Adapters:
DockerSandbox,E2BSandbox,LocalSandbox(development only) in both runtimes;ComputeSdkSandboxin TS; a memory one for tests. - One sandbox per thread, kept between messages. It ends when the thread is deleted, after
sandboxIdleTtlMsidle (30 min), or aftersandboxMaxLifetimeMs(24 h). An idle sandbox shuts itself down, even with no app running. withSandbox(opts, fn)(Go:WithSandbox) gives your own tools the thread's sandbox.
Sandbox tools
bash: each command starts in the folder the last one ended in. Asks for approval by default.code_execution: runs Python or JavaScript, lists the files it made, and streams its output as it prints. Does not ask.text_editor: view, create,str_replace, insert and undo. Asks for changes, not for view.approvaltakestrue,falseor a check per call. There's a time limit and a limit on uses per run. Long output keeps its start and end. Output streams live astool.outputevents.
Also
SqliteKv(agentenkit/adapters/sqlite), the TS twin of Go'ssqlite.NewKv, with a shared kv test suite in both runtimes.- Examples: four small apps with nothing to stand up (
web-tools-ts,web-tools-go,sandbox-tools-ts,sandbox-tools-go) sharing one page. The Next.js and Go examples use the tools, and the admin view shows a thread's spend, tool calls included. - Docs: new Web tools and Sandboxes pages.