Releases: microsoft/amplifier-agent
v0.9.0
What's new in 0.9.0
The headline: opencode and any OpenAI-compatible client now get full session continuity with zero config. Before 0.9.0, every chat-completions request created a new amplifier session with a random sid; one opencode conversation fragmented into N session dirs. With 0.9.0, the amplifier session_id is derived from the client's session header (sent automatically by Vercel AI SDK), so one opencode conversation = one amplifier session — unified audit trail, persistent hook state across turns, append-mode events.jsonl.
Added
-
Chat-completions session resume via
X-Client-Session-Id/X-Session-Id. Server now uses a deterministichttp-<client_sid>as the amplifier session_id, auto-detects first-turn vs continuation by checking if the session state dir exists on disk, and passesis_resumedto the kernel resume mechanism (same primitiveamplifier-agent run --resumeuses). One client conversation = one amplifier session. (#71) -
X-Session-Idheader fallback — opencode and other Vercel AI SDK-based clients send this header automatically. amplifier-agent now recognizes it as a fallback forX-Client-Session-Id, so session-resume works out of the box for opencode with zero client config.X-Client-Session-Id(our amplifier-native convention) remains authoritative when both are present. (#72) -
Client-authoritative transcript reconciliation in
_reconciler.py. The chat-completions wire is stateless — clients send full history every turn. On divergence between stored and incoming, the client wins by fiat: we persist their view over ours without any rewind ceremony. (#71)
Changed
-
reconcile_client_historynow runs foundation's transcript-repair pass before persisting. Catches broken chat-completions clients (orphanedtool_usewithout pairedtool_result, ordering violations, incomplete assistant turns) that would otherwise cause Anthropic to reject the next LLM call with HTTP 400. Mirrors_runtime.py:_repair_loaded_transcript_if_neededfrom the CLI face. Healthy transcripts pass through unchanged (<10ms diagnostic). (#73) -
Workspace name is no longer suffixed with the client session id. Previously,
X-Client-Session-Id: abcwould route requests intoworkspaces/<base>-abc/. Now the workspace stays at<base>and per-client distinction is purely at the session_id level (workspaces/<base>/sessions/http-abc/). This keeps workspace-level hook state shared across all sessions of the same server process, where it belongs. (#72)
Wire protocol
Unchanged at 0.3.0. No wrapper bump. TypeScript wrapper stays at 0.7.0.
Backward compatibility
- Clients NOT sending
X-Client-Session-IdorX-Session-Id: behavior unchanged — random sid per turn, no resume. - Clients sending only
X-Client-Session-Id: behavior unchanged from PR #71. - Clients sending only
X-Session-Id(opencode default): NEW — gets full session continuity. - Clients sending both:
X-Client-Session-Idwins.
The wire format (request body, response body, headers) is unchanged. The only observable difference for existing clients is the on-disk workspace dir layout — workspace name is no longer suffixed with the client session id.
See CHANGELOG.md [0.9.0] for full details, including the [0.8.0] section which still applies.
v0.8.0
What's new in 0.8.0
Added
-
OpenAI-compatible chat-completions HTTP face (
amplifier-agent serve chat-completions) —/v1/models+/v1/chat/completionsover HTTP with bearer-token auth. Streams responses, multi-provider routing via served-models registry, workspace correlation throughX-Client-Session-Idheader. Enables direct integration with opencode via theamplifier-app-opencodewrapper and any OpenAI-compatible client. (#65) -
amplifier-agent authsubcommand — set/list/remove/status/clear actions over~/.amplifier-agent/credentials.json(mode 0600). Resolution chain is env-first: shell env vars (ANTHROPIC_API_KEY, …) win over the file so existing shell-rc workflows are unchanged. "Set once, works everywhere" UX matchingclaude login/gh auth login/aws configurewithout the OAuth ceremony. (#65) -
Host-tool delegation — tools declared by the host (
host_config.json:host_tools) are surfaced to the model with stub schemas; on invocation, server emits a signal tool_call back to the client (samechunk_id), client executes host-side, returns result for the model to continue. Lets the host own filesystem, shell, browser, or any custom tool without bundling into amplifier-agent. (#65) -
Model routing matrix integration — per-role provider/model preferences resolved per turn. (#64)
-
cost_usdin chat-completions usage envelope — non-standard field carrying the actual dollar cost provider modules computed, accumulated across sub-turns, serialized as a string for Decimal precision. Standard OpenAI clients ignore the field; cost-aware clients render the real per-turn $$. (#68) -
host_config.providers(plural) registry — declares which providers the server-mode lifespan loads and how to instantiate each. Schema:providers: {<provider_id>: {module?: str, config?: dict}}. Module defaults to provider_id when omitted; each provider's config is passed asextra_configintolist_provider_models(). (#69) -
amplifier-agent serve status / stop / restartsubcommands — operational lifecycle for the chat-completions HTTP server. Status reports running/stale/not-running, where it's reachable, and how many models from which providers it's serving (self-cleans stale state files when the PID is gone). Stop sends SIGTERM with a configurable graceful-exit window (--timeout), escalating to SIGKILL on expiry or on--force. Restart performs an identity-restart using the args stored at original launch. State is tracked in~/.amplifier-agent/state/serve.json(mode 0600, parent dir 0700; api_key is sensitive and never logged). (#69)
Changed
-
Breaking (server mode only):
amplifier-agent serve chat-completionsnow requireshost_config.providersto be a non-empty dict. Any provider declared there that cannot initialize (missing credentials, module not installed,list_models()raises, returns 0 models) causes the server to exit 2 with a structured error listing every problem. The previous behavior — iterating a hardcodedKNOWN_PROVIDERSlist, silently skipping unreachable providers, and falling back to an unusable placeholderamplifiermodel — is gone. Single-turn mode (amplifier-agent run) is unaffected. (#69) -
POST /v1/chat/completionsnow validatesmodelagainst the served registry. Requests with an unknown model return HTTP 400{"error": {"code": "unknown_model", ...}}immediately, instead of being silently routed to whichever provider loaded first and failing 4 seconds later with an upstreamnot_found_errorembedded indelta.content. (#69) -
stream: falseis now honored. Requests with that flag return a single JSON body; onlystream: true(or absent) uses SSE. (#69) -
Upstream errors raised before any content chunks are emitted now surface as HTTP 502 with a structured OpenAI-shape error envelope, instead of being embedded inside
delta.contentof a 200 SSE response. (Mid-stream errors after the first chunk remain embedded indelta.content— once SSE starts, the status line is committed.) (#69) -
/v1/modelsno longer falls back to a placeholder{"id": "amplifier", ...}entry. The lifespan guaranteesserved_models_registryis non-empty (or the server exits at boot), so the fallback was unreachable in practice. (#69) -
Lifespan provider iteration now reads from
host_config.providersinstead of the hardcodedKNOWN_PROVIDERScatalog. The CLI'sKNOWN_PROVIDERSconstant stays defined for single-turn mode and other CLI commands. (#69) -
/v1/modelsresponse surfaces a_providertag per model so OpenAI-compatible clients can see which provider serves each entry. (#65) -
Usage-counter telemetry in chat-completions responses correctly reflects the provider that actually served the turn. (#65)
Wire protocol
Unchanged at 0.3.0 — no wrapper bump. TypeScript wrapper stays at 0.7.0, Python wrapper stays at 0.3.0.
Migration
Existing server-mode users (anyone running amplifier-agent serve chat-completions on a 0.7.x or pre-#69 0.8.0 commit): Add a providers block to your host_config.json. Minimum to keep working with just Anthropic:
{
"providers": {
"anthropic": {}
}
}Multi-provider example:
{
"providers": {
"anthropic": {},
"openai": {"config": {"base_url": "https://api.openai.com/v1"}}
}
}Without host_config.providers, the server will exit at boot with a clear error message rather than running in a broken half-state.
No other breaking changes. Existing CLI (run, models list), JSON-RPC wire, single-turn mode, and HTTP clients reading standard OpenAI fields all continue to work.
See CHANGELOG.md [0.8.0] for full details.
v0.7.0
What's Changed
- feat(wrapper-py): replace amplifier-agent-client with amplifier-agent-py at protocol 0.3.0 by @manojp99 in #56
- refactor(persistence): align cwd-derived workspace slug with amplifier-app-cli by @manojp99 in #57
- docs: scrub README + add AGENTS.md by @manojp99 in #58
- feat(engine): replace built-in bundle with vendored behavioral-anchor by @manojp99 in #59
- chore(release): bump engine to 0.7.0 by @manojp99 in #63
Full Changelog: v0.6.0...v0.7.0
What's Changed
- feat(wrapper-py): replace amplifier-agent-client with amplifier-agent-py at protocol 0.3.0 by @manojp99 in #56
- refactor(persistence): align cwd-derived workspace slug with amplifier-app-cli by @manojp99 in #57
- docs: scrub README + add AGENTS.md by @manojp99 in #58
- feat(engine): replace built-in bundle with vendored behavioral-anchor by @manojp99 in #59
- chore(release): bump engine to 0.7.0 by @manojp99 in #63
- feat(routing): integrate model routing with per-provider matrix selection by @manojp99 in #64
Full Changelog: v0.6.0...v0.7.0
v0.6.0
What's Changed
- feat(streaming-hook): enrich wire events with cost, LLM timing, model, thinking, and sub-agent attribution by @manojp99 in #45
- feat: workspace identity + per-workspace storage + context-intelligence hook (with fork-pin disclosure) by @manojp99 in #46
- Feat/workspace implementation by @manojp99 in #47
- feat: structured NDJSON wire-event consumption, --workspace forwarding, prepare script by @manojp99 in #48
- feat(storage): unify on ~/.amplifier-agent, drop XDG path resolution by @manojp99 in #50
- feat: model/effort overrides + models list discovery command by @manojp99 in #49
- feat(cli): default --output to text, reject conflicting flag combinations by @manojp99 in #51
- refactor(migration): make migrations user-invoked via 'amplifier-agent migrate' by @manojp99 in #52
- feat(wrapper-ts): add listAllModels() for aggregate provider discovery by @manojp99 in #54
- chore(release): bump engine to 0.6.0 and TS wrapper to 0.7.0 by @manojp99 in #55
Full Changelog: v0.5.2...v0.6.0
wrapper-v0.7.0
What's Changed
- feat(streaming-hook): enrich wire events with cost, LLM timing, model, thinking, and sub-agent attribution by @manojp99 in #45
- feat: workspace identity + per-workspace storage + context-intelligence hook (with fork-pin disclosure) by @manojp99 in #46
- Feat/workspace implementation by @manojp99 in #47
- feat: structured NDJSON wire-event consumption, --workspace forwarding, prepare script by @manojp99 in #48
- feat(storage): unify on ~/.amplifier-agent, drop XDG path resolution by @manojp99 in #50
- feat: model/effort overrides + models list discovery command by @manojp99 in #49
- feat(cli): default --output to text, reject conflicting flag combinations by @manojp99 in #51
- refactor(migration): make migrations user-invoked via 'amplifier-agent migrate' by @manojp99 in #52
- feat(wrapper-ts): add listAllModels() for aggregate provider discovery by @manojp99 in #54
- chore(release): bump engine to 0.6.0 and TS wrapper to 0.7.0 by @manojp99 in #55
Full Changelog: v0.5.2...wrapper-v0.7.0
v0.5.2
What's Changed
- fix: make timeout opt-in instead of silently imposing 10-min wall-clock cap by @bkrabach in #41
- fix(runtime): repair orphaned tool calls in resumed transcripts by @manojp99 in #43
- chore: bump amplifier-agent to 0.5.2 by @manojp99 in #44
New Contributors
Full Changelog: v0.5.1...v0.5.2
wrapper-v0.6.2
v0.5.1 — hooks-approval unmounted from default bundle
Highlights
hooks-approval is no longer mounted by default. Per the upstream USAGE_GUIDE — "Backward compatible — Tools work without approval hook." — the module is opt-in. The engine's default bundle had been mounting it unconditionally, which caused sub-session delegation to auto-deny any command that fell outside the bundled DEFAULT_RULES auto-approve list (e.g. cat, env, curl).
What changed
- Removed
hooks-approvalfrom the default bundle composition (src/amplifier_agent_lib/bundle/bundle.md) - Updated
admin/doctor.pyto drop thehooks-approvalpresence check (it would have permanently failed post-unmount) - Updated
tests/test_admin_doctor_phase2.pyto match the new doctor expectations - Added
ISSUES.mdtracking the deferred work needed to re-wirehooks-approvalend-to-end in the future (5 concrete pieces — see ISSUE-001) - Bumped
pyproject.toml:0.5.0→0.5.1
The LICENSE is unchanged. Pre-PR 0.5.0-era sessions remain resumable but delegation flows will still hit the old auto-deny behavior on those sessions; start a fresh session to get the new behavior.
How to install
uv tool install --reinstall --force git+https://github.com/microsoft/amplifier-agent@v0.5.1Compatibility
- Wire protocol:
0.3.0(unchanged from 0.5.0) - amplifier-agent-ts wrapper:
>= 0.6.1 - Hosts: any caller using
host_config.approval.mode = "yes"or passing-yworks unchanged
Why this matters
For hosts running headless (paperclip, CI/CD), the engine no longer requires a separate hooks-approval registration step. For interactive CLI use, add hooks-approval to your profile per the USAGE_GUIDE.
Reference
🤖 Generated with Amplifier
What's Changed
- feat(wrapper-ts)!: hardening release 0.6.0 (NDJSON events, configPath, approval, getEngineInfo, +5 more) by @manojp99 in #36
- fix(wrapper-ts): transport test timeout for CI (v0.6.1, supersedes failed 0.6.0 publish) by @manojp99 in #37
- feat(cli): amplifier-agent update subcommand (v0.5.0) by @manojp99 in #38
- fix(bundle): unmount hooks-approval from default mount (v0.5.1) by @manojp99 in #40
Full Changelog: v0.4.1...v0.5.1
v0.4.1
What's Changed
Full Changelog: v0.4.0...v0.4.1
v0.4.0
What's Changed
- fix(catalog): default openai to gpt-5.5 (matches bundle's extended_thinking=true) by @manojp99 in #20
- docs(readme): align with Mode A pivot, protocol 0.2.0, and shipped L3 wrappers by @manojp99 in #21
- fix(cli,lib): wire PROTOCOL_VERSION import + track pyproject for version by @manojp99 in #22
- fix(cli): align Azure provider env var with docs (prefer AZURE_OPENAI_API_KEY, accept legacy AZURE_OPENAI_KEY) by @manojp99 in #23
- chore(deps-dev): Bump vitest from 1.6.1 to 4.1.0 by @dependabot[bot] in #26
- fix(wire): align all sites to protocol 0.2.0 (--mcp-config-path, schema rename, fixture bump) by @manojp99 in #24
- docs: add canonical Microsoft Trademarks section to README by @sadlilas in #28
- feat: host config layer + drop hostCapabilities surface by @manojp99 in #27
- chore(cli)!: drop --mcp-config-path argv flag (subsumed by host config + env var) by @manojp99 in #29
- feat: host-config skills: block (D11/D12/D13) + tool-skills bundle composition by @manojp99 in #30
- chore(wrappers)!: drop env-allowlist, env-extra, allow-protocol-skew from wrappers (sync with engine) by @manojp99 in #31
- chore(conformance): restore wrapper-engine cross-validation (post-#24, #27, #29, #31) by @manojp99 in #32
- feat: engine-hardening — fail-fast on headless approval ambiguity (G3) + mcp engine dependency (G4) + host_config schema reference (N1/N2) by @manojp99 in #34
- chore!: release 0.4.0 — host config layer, surface cleanup, conformance restored by @manojp99 in #33
New Contributors
- @dependabot[bot] made their first contribution in #26
- @sadlilas made their first contribution in #28
Full Changelog: wrapper-v0.4.0...v0.4.0