Skip to content

v0.3.0 — reshaped in Go, grown into a workbench

Latest

Choose a tag to compare

@github-actions github-actions released this 14 Aug 11:20
· 15 commits to main since this release

🛠️ agents-go v0.3.0 — reshaped in Go, grown into a workbench

v0.2.0 declared independence; v0.3.0 spends it. 153 commits since v0.2.0; 598 files changed, +52k/−19k lines. Three arcs run through this release: the SDK's public surface is reshaped around Go rather than around its Python ancestry (the batched breaking changes below are the price, paid once), Anthropic becomes a first-class second backend behind the same canonical Responses format, and agents-server grows from a demo into a workbench — providers, deterministic workflows, plan mode, and a context panel that shows where your window actually went.

Breaking changes

Batched per spec §5.8 — public API compatibility begins at v1.0.0; old spelling beside new.

  • A tool is a struct. The Tool interface and FunctionTool collapse into one concrete Tool struct — there is nothing left for a hosted tool to implement, which is the point. Optional capabilities remain side interfaces discovered with ToolAs.
  • An item is a struct. The RunItem interface collapses into one struct with a Kind.
  • Stored history moves to agents/sessionStorage, Session, Projector, entries and their value types live there now (aliased in agents); the JSONL store is renamed filesession (its old package name, memory, was its opposite).
  • mcp is its own module — the go-sdk dependency leaves the core; the import path is unchanged.
  • Handoffs declare their graph staticallyHandoff.Target replaces runtime discovery.
  • The naming batch aligns the model surface (Respond / StreamResponse, InputItem, …) and drops zero-consumer exports across the SDK.
  • Instructions and PromptProvider are func types; compaction.PreserveSystem *bool becomes DropSystem bool; errors carry one classification and a failed run still carries its RunResult.
  • tasks.Store shrinks: the notify state machine (ConsumeNotify, MarkNotifyDelivered, ListPendingNotify, PendingNotifyParents), Config.Guard and NotifyFormatter are gone — the Manager reports endings (OnFinished / OnResultDelivered) and delivery is the host's, with the durable-host obligations recorded in the spec.
  • agents-server: credentials move off agent configs into first-class provider rows; agents and routes reference a provider_id.

Highlights

A second backend, one canonical format

  • models/anthropic — the Messages API as a full Model implementation, translated inside the adapter to the same canonical Responses format everything else speaks (spec §5.10). Extended thinking, tool use, prompt caching.
  • models/modelkit — the dependency-free adapter toolkit, plus modelkit/conformancetest: a golden matrix every Model implementation must pass, so a third backend starts from a test suite instead of a guess.
  • ChatGPT (Codex) subscriptions served through a stream-only Model decorator — blocking calls ride a stream underneath.

agents-server becomes a workbench

  • Providers — one masked credential surface; ChatGPT OAuth login lives per provider; prefix routes and fallbacks resolve through the same rows.
  • Workflows — fixed step sequences (plan → exec → verify, each step its own agent and model) running on a hidden child session, advanced by compare-and-set from run teardown, with on_success/on_failure edges, retry-from-the-failed-step, and dismissal. Started only by the agent (start_workflow) — the brief has to be written by something that read the conversation.
  • One wake-up debt — tasks and workflows share a wakeups table; the debt lands in the same transaction as each terminal state, so a crash can never leave finished work whose conversation is never told.
  • Plan mode — a session-level restraint the person toggles with the message; gated tools stay visible and refuse while planning (backed by the new Tool.ReadOnly), and the refusal outranks approval.
  • The Context panel — one window bar with the compaction threshold as a tick on it, the window's composition as honest same-ruler shares (prompt layers, tool schemas, the conversation), per-call growth, cache hits, and a Compact-now button.
  • Sandboxes as facts — a session's sandbox binding is a stored, versioned fact bound by CAS at run start; persistent exec_command shells on terminal-capable backends; a real web terminal.

Background work grows up

  • Task retry-in-placefailed → working is a store-level compare-and-set with the attempt ceiling enforced by the database; every attempt-scoped write names its attempt.
  • Replay, traced — the replay dialog reruns a call with schema/handoffs fidelity, SSE streaming, diffs and attempts.

Hardening, everywhere

  • Severed model streams recover mid-turn; truncation classifies retryably.
  • MCP shared connections survive one run's cancellation and redial themselves from the config that made them.
  • Injected input is transactional against the turn that holds it; overflow recovery accounts for every item, on-chain or off.
  • The session lifecycle, run-state resume window (spec §5.18), and the task state machine each took a dedicated audit-and-fix pass — the Fixes list below is that work.

Changelog

Fixes

  • 6819ef8 fix(agents): commit injections only against a home that holds them; seed resume backlog eagerly
  • cd0d846 fix(agents): injection transaction, usage snapshots, RunState wire completeness, abandonment cancellation
  • cc841c3 fix(agents,models): recover severed streams — hold back pre-commit events, classify truncation retryably
  • 55cd2d2 fix(agents-server): render a failed run's partial text as prose, not a chip
  • 664f925 fix(compaction): summary prompt asks for plain prose over a transcript
  • eab897f fix(handoff): validate the whole input schema, not root-level required
  • e6ca8ed fix(mcp): a request on the shared connection never carries a caller's cancellation
  • b80785a fix(mcp): pass multi-block tool results through as native content parts
  • 94ea481 fix(mcp,toolchain): boundary fixes across mcp, tracing, tasks and the dev tools
  • d5c0623 fix(models,session): record a committed fallback break, and align InMemoryRepo.List
  • d578024 fix(models/openai): guard the server-side compaction rewrite with a last-seq check
  • c00a32b fix(otel): stamp workflow attributes on every root span of a trace
  • d0dac77 fix(run)!: injected input gets a real stream event name
  • fde6166 fix(run): ResumeRun adopts a copy of the pause state's usage
  • 2c10823 fix(run): a chain-built rewrite no longer deletes what the chain never saw
  • b521036 fix(run): a projector that withholds an item puts it off the chain too
  • e07d86e fix(run): a windowed read and a handoff filter also put items off the chain
  • 5855cbd fix(run): overflow recovery keeps injected input the run had not stored yet
  • 6ae8e6a fix(run): overflow recovery writes the turn on the side of the pass it survives
  • cd6a515 fix(run): the forced pass on overflow reports off-chain items too
  • 9514a6b fix(runstate): resume starts like a fresh run, and the decode window promises only what it can keep
  • 3bcd000 fix(sandbox): a malformed exec_command call costs the call, not the run
  • 5596023 fix(sandbox): advertise session_id in exec_command schema only when Sessions is on
  • 1b24e47 fix(sandbox): give file tools exec's path view instead of a workdir chroot
  • 5d2e26a fix(sandbox): make Policy compilation concurrency-safe
  • 7a7fefa fix(sandbox): only null, 0 and false read as "none"; other scalars are refused as text
  • 3ada563 fix(server): a cancelled run says so, and the bridge stops reaching past the store
  • b37f50e fix(server): a tool result's display reaches the live card
  • f531ae3 fix(server): restore per-method BeforeAppendModel doc comments required by revive
  • 9cbe2b6 fix(server): test sinks count atomically; detach does not join the delivery goroutine
  • 99a9b88 fix(session): equalDisplay compares Title and Summary too
  • a0bb14e fix(tasks): a run cannot outlive the task that started it
  • abd007d fix(tasks): a stop says what it did, and a fast finish is not a cancellation
  • af221c1 fix(tasks): a stop that hears "already finished" looks again
  • 657dcdb fix(tasks): stamp the spawning run's id on spawned tasks
  • f543f80 fix(tasks): tell the model the result, or owe it — never neither
  • 390a498 fix(tasks): the debt of a failed retry follows who was told
  • 74b3242 fix(tasks,agents-server,web): a stop waits out a late outcome, and claims a lost one
  • 89f4d75 fix(tools)!: AsTool's default input goes through schema validation
  • fe0f612 fix(tools): name a nil Agent.Tools entry instead of panicking
  • e461092 fix(verifydocs): widen the package list and stop prose from hiding references
  • 72b67cc fix(web): a voided attempt's summary does not outlive it
  • e3760ac fix: repair two regressions found reviewing the interface collapses
  • 4792bce fix: review pass over the naming batch and the session split

Changes

  • 79b1fce build: ignore the working plan for this review pass
  • deda114 feat(agents): plan mode denies instead of hiding, backed by Tool.ReadOnly
  • 1f661a3 feat(agents): stream-only Model decorator; serve ChatGPT Codex blocking calls through it
  • 8036115 feat(display): Title and Summary are first-class, from the tool to the card
  • b4137eb feat(handoff)!: Target declares the handoff graph statically
  • e318576 feat(mcp,agents-server): a dead connection redials itself from the config that made it
  • 8324815 feat(runstate): Extra carries host state across a pause, and the server stops destroying decodable states
  • 483ab70 feat(sandbox): a docker project lives in a /workspace subtree, adopted only by fingerprint
  • 9cbc84a feat(server)!: providers, workflows and the wake-up debt
  • 388a6eb feat(server): a run binds its sandbox at start; instances retire by content generation
  • 64f4969 feat(server): a session's sandbox binding is a stored, versioned fact
  • da7ef60 feat(server): persistent exec_command shells on terminal-capable sandboxes; raise tool output caps
  • 2f263c8 feat(server): retry a failed task from the API, and fix what that exposed
  • 01ae18a feat(server): sandbox writes are strict, revisioned, and sever stale terminals
  • f173be6 feat(server): session context report, prompt profile and manual compaction
  • 8fca3ab feat(server): the REST surface for providers, workflows and the context report
  • 92a28d0 feat(session): UserText reads the user-authored text of an input slice
  • fed679f feat(stream): ItemsPersistedEvent announces the persist boundary
  • a9815b7 feat(stream): the tool_called wrapper of a handoff says what it wraps
  • 494eb33 feat(tasks): a failed task can be resumed instead of started over
  • e5c2a69 feat(tasks): attempt-scoped writes name their attempt, and one suite holds three stores to it
  • 28b25b3 feat(tasks): hand a wake-up launch its lineage
  • 0faa732 feat(tools): NewToolNonStrict, and strict-schema errors that name a real exit
  • 2b807e6 feat(tracing): record call_id on function spans
  • a2cfdf1 feat(web): Context panel, and the decoupling it exposed
  • a22e7f2 feat(web): a chat top bar names the session and hosts the panel entries
  • f74b360 feat(web): retry a failed task, and stop the card lying while it runs
  • 20c5778 feat(web): the composer picks a project; a bound session shows it read-only
  • fa52dad feat(web): workflows, providers, plan mode and the context panel redesign
  • 1cf9108 perf(server): materialize the append point, and hold it to the fold
  • 8563a62 refactor!: drop zero-consumer public surface across the SDK
  • f453d15 refactor(agents)!: Instructions and PromptProvider become func types
  • 3b413ff refactor(agents)!: one channel per concern in the tool and agent-tool API; split run_step.go
  • 5355fcd refactor(agents): fold hand-rolled helpers into the stdlib
  • 442bd09 refactor(agents,models,agentstest)!: fold duplicated plumbing; fix log-level and Sensitive semantics
  • 61c6104 refactor(agents-server): drop the Runner task facade the SDK tools replaced
  • 91421a0 refactor(agents-server): one run pipeline, handler-owned routes, leaner hub plumbing
  • 65ba8fe refactor(api)!: finish the naming batch
  • 91d0464 refactor(compaction)!: PreserveSystem *bool becomes DropSystem bool
  • 40b989d refactor(errors)!: one classification, and failed runs carry a RunResult
  • c41e0e0 refactor(filesession)!: rename the memory package, whose contents were its opposite
  • 38264b1 refactor(guardrail): dedup result construction into newGuardrailResult
  • 0ed0972 refactor(items)!: collapse the RunItem interface into one struct with a Kind
  • 7dc7906 refactor(mcp)!: fold RequireApprovalFunc into RequireApproval; reject conflicting naming options
  • 03d7a9b refactor(mcp)!: split into its own module so the go-sdk stays out of the core
  • b2cf726 refactor(mcp): blank the OnInvoke ToolContext param the meta-resolver removal orphaned
  • f4290db refactor(middleware): remove Logging, the demo middleware with no consumer
  • f7bb3f0 refactor(models): keep retry in one layer, disabling the client default
  • 7f4fd3c refactor(run): collapse the loop's state, and let a cancelled boundary carry progress
  • 1b5450d refactor(run): decompose loop's NextStep switch into named step handlers
  • 9af6fe5 refactor(run): extract emitItems/appendInjected helpers, dedup injected-input handling
  • b8ae25f refactor(sandbox): share ShellQuote across backends, plus small cleanups
  • 9164820 refactor(sandbox/docker): one exec core per mode, and the split that hid a bug
  • 4f35402 refactor(server): decompose buildAgentFromConfig
  • f032f4e refactor(server): drop the dead ctx parameters staticcheck caught
  • bfd14b4 refactor(server): share the REST error envelope, and modernize errors.As
  • c4b3693 refactor(server,models): split the stream bridge, share the usage and event vocabularies
  • adf4dcf refactor(session)!: extract stored history into agents/session
  • 5f7202c refactor(session)!: three shapes on the session surface
  • c38d031 refactor(session): remove the pop/undo storage primitive with no callers
  • aa902ff refactor(session): share what was copied, prune what rotted
  • 442ec3c refactor(sessions)!: task store on the reporting contract
  • 3c4694b refactor(tasks)!: the Manager reports endings; delivery becomes the host's
  • 736a845 refactor(tasks): collapse the four host hooks to func types
  • eb58787 refactor(tools)!: collapse the Tool interface into the FunctionTool struct
  • 49cee4a refactor(tools)!: rename FunctionTool to Tool
  • c1af8e4 refactor(web): the default session name says session, not chat
  • 2b3dc63 style(server): gofmt tab-align swagger annotations in sandbox.go
  • c21743d style(web): tighten the chrome, and drop the Tasks item that led nowhere
  • 9ba0b07 style: comments keep the invariant and drop the campaign

Full Changelog: v0.2.1...v0.3.0