AgentDeck 6.0 is here: serve one deck over HTTP, AG-UI or the terminal.See what's new
AgentDeckv6.0.6
Resources

Migration Guides

v5 to v6.0.0

See What's new in 6.0 for the model behind this release. v6.0.0 replaces the v1 HTTP wire with bindings: a Deck is served over one or more of them, never itself. agentdeck chat is unchanged.

breakbefore (v5)after (v6.0.0)
v1 routes gonePOST /agents/{name}/chatPOST /runs, then GET /runs/{run_id}/events
agentdeck-serve gone; deck.serve(...) is the new front dooragentdeck-servedeck.serve(Native.http("/api"), port=8000)
Deck.asgi() needs a bindingDeck.from_project().asgi()Deck.from_project().asgi(Native.http())
the error taxonomy moved off the root packagefrom agentdeck import ConfigErrorfrom agentdeck.errors import ConfigError
InputError replaces raw TypeError/ValueError for caller inputexcept (TypeError, ValueError)except InputError
InterruptReason drops "approval"pending.reason == "approval"pending.reason == "human"; refusal comes from payload["options"], which Run.answer already enforces

v4 to v5.0.0

v5.0.0 is a breaking release: a v5 build cannot read an event log v4 wrote, and several public names moved. There is no compatibility shim for any of these. Read every section before upgrading a running deployment.

Event log: v5 refuses a v4 log

The envelope's schema version bumped from major=3 to major=4. SQLite and Postgres refuse a 4.x log outright, before parsing a single event:

StoreOn a 4.x log
SQLiteDeck opening it raises StoreError
PostgresSame: StoreError
RedisNo such check. Its keys were shaped differently under 4.x; do not point a v5 process at 4.x Redis data
from agentdeck import Deck
from agentdeck.errors import StoreError

try:
    async with Deck.from_project() as deck:
        pass
except StoreError as exc:
    print(exc)

The message names exactly why:

the event log at '<path>' was written by agentdeck 4.x (its 'events' table still has the
'log_key' column 5.0 replaced with 'session_id'). agentdeck 5.0 does not migrate a 4.x log:
replay it into a new store, or reopen it with the 4.x version that wrote it.

Underneath that guard is a second, unconditional one: Event itself refuses any schema major but its own, so even a hand-rolled reader cannot mix the two.

What to do: drain a 4.x deployment (let every open run finish under v4) before pointing a v5 process at its store, or keep the v4 build around to read that log. There is no migration path and no store that reads across the boundary.

EnginePort is Executor, and start/resume become one execute

v4v5
EnginePort (in agentdeck.core.ports)Executor
agentdeck/adapters/engines/agentdeck/adapters/executors/
InvocableSpec.engineInvocableSpec.executor
EnginePort.start(...) and EnginePort.resume(...), two methodsExecutor.execute(...), one method

This is a restructuring, not a rename. execute takes the same history a resumed run always carried, and reads off it whether this play is fresh, a replayed pause, or an answered interrupt; there is no separate resume left to implement. Executor.aclose() is new and optional (default: no-op) for an executor that holds something to release when the deck closes.

What to do: fold a custom EnginePort.start/resume pair into one Executor.execute. Wire values are unchanged: an executor is still selected by the name it always used ("native", "openai-agents", "stub"), and run.failed still carries error_code="engine_error".

LangGraph is removed, not deprecated

agentdeck/adapters/engines/langgraph/ and the langgraph dependency are gone. There is no drop-in replacement.

What to do: rewrite a LangGraph-backed workflow as a native @workflow, which needs no engine at all.

EventSinkPort is Observer

from agentdeck import Observer
from agentdeck.observers import ConsoleObserver, FileObserver, LangfuseObserver

print(Observer.__name__, ConsoleObserver.__name__, FileObserver.__name__, LangfuseObserver.__name__)
v4v5
EventSinkPortObserver
agentdeck.observers.Langfuseagentdeck.observers.LangfuseObserver

ConsoleObserver and FileObserver are new in v5, alongside the rename.

What to do: rename Langfuse(...) to LangfuseObserver(...) wherever it is constructed, and EventSinkPort to Observer in any custom implementation.

Runtime settings: no config.yaml

v4 read settings from environment variables, a project .env, and a shared config.yaml (resolved via AGENTDECK_CONFIG_PATH → cwd → a packaged default). v5 removes the YAML source entirely: every setting comes from a process environment variable or the project's .env, and nothing else.

What to do: move every key a config.yaml held into AGENTDECK_* environment variables (see the full list on the Settings reference), and delete the file. A config.yaml left behind is not read.