Core Concepts
AgentDeck owns configuration; the OpenAI Agents SDK and LangGraph own execution. You write a few kinds of definition, and the platform supplies everything around them.
| You write | It is | Runs on |
|---|---|---|
| Agent | keyword arguments: instructions, tools, handoffs | OpenAI Agents SDK |
| Skill | a directory: SKILL.md + optional scripts | disclosed into an agent’s own execution |
| Workflow | typed state + a graph | LangGraph |
The shape of a project
Everything lives in .agentdeck/ next to where you run. The path is the registration —
no catalog file, no __init__.py, no decorator to remember.
.agentdeck/
├── agents/greeter/agent.py # an Agent(...)
├── workflows/new_booking/workflow.py # a Workflow(...)
└── skills/parse-request/ # SKILL.md + scripts/Deck.from_project() discovers, imports, and compiles all of it, and fails fast if anything is
broken:
import asyncio
from agentdeck import Deck
async def main() -> None:
async with Deck.from_project() as deck:
print(sorted(deck.agents), sorted(deck.workflows))
asyncio.run(main())What runs a turn
Deck is also the composition root: it wires the discovered project into one Runtime and hands
it to whatever is serving. A chat served over HTTP — POST /agents/{name}/chat, streamed or not
— is played by that Runtime, which records the turn as an event log: the run opening, text
deltas, tool calls, token usage per model call, then the result. The log is in memory by default;
set AGENTDECK_EVENTS=sqlite:///path/to/events.db to keep it across restarts, or
redis:///postgresql:// for a log that several workers can share — the URL’s own scheme
picks the backend. SQLite’s file can be opened by several processes on the same machine, but
not from a second one, which is why redis and postgres exist as separate options rather
than “just point everyone at the same file.” The Python API (Deck.run, Deck.stream) plays the turn on the same
Runtime, so it records the same events — same agent, same session, same answer, same log.
The division of labor
Deterministic code mutates external state; models decide. A model call never writes to your systems directly — a node or a tool does, and those are ordinary Python you can test without a model.
Agents, workflows, and skills compose in any direction: an agent can be a workflow node
(AgentNode), a workflow can be an agent’s tool
(Workflow.as_tool()), and a skill can be declared on any agent that needs it, workflow node
or not.
Whatever the shape, a run in flight stays governable: it can be paused, resumed and cancelled by its id, at documented safe points — see Run Control.