AgentDeck SDK
Agentic software should feel like software.
Build agents, tools and workflows as normal software. AgentDeck gives them one execution model you can observe, control and extend.
pip install agentdeck-sdk
Built to stay out of your way
Agent systems accumulate infrastructure quickly, and decisions that look small early are the hardest to change later.
Execution, control, state, observability, reporting, interaction, and integration already have their place in AgentDeck, and they were designed to work together: less machinery to build today, and nothing to retrofit around your application when you need the next one.
Simple code. Serious capabilities.
Your code stays about the behavior and structure of your application:
- Tools do work: Plain Python functions or
@tooldecorators. Tools declareToolCtx[T]to receive strongly typed application data without exposing internal state to the model prompt. - Agents make decisions: Declarations configuring model instructions, tools, skills, and handoffs.
- Workflows manage process: Ordinary async Python functions decorated with
@workflow. UseWorkflowCtxto invoke targets (ctx.invoke), branch in parallel (ctx.parallel), or park for human input (ctx.ask). - Decks assemble applications:
Deckis the single composition root. It validates dependencies, schemas, and catalogs at startup before the first turn.
from agentdeck import Agent, Deck, ToolCtx, WorkflowCtx, tool, workflow
class AppContext:
def search(self, query: str) -> str:
return "Internal records found."
@tool
def lookup_records(query: str, ctx: ToolCtx[AppContext]) -> str:
"""Look up internal records."""
return ctx.data.search(query)
agent = Agent(
name="SupportBot",
instructions="Help users resolve inquiries using internal tools.",
tools=[lookup_records],
)
@workflow
async def handle_request(ctx: WorkflowCtx, ticket: dict) -> str:
"""Coordinate support tasks with human approval for sensitive changes."""
response = await ctx.invoke(agent, ticket["query"])
if ticket.get("urgent"):
approved = await ctx.ask(f"Approve urgent response for ticket {ticket['id']}?", options=[True, False])
if not approved:
return "Escalated to human supervisor."
return response
deck = Deck(agents=[agent], workflows=[handle_request], context=AppContext)
You build the behavior. AgentDeck manages the machinery.
Run
├── executions nested invocations, each addressable
├── events one ordered log per run
├── reports progress and status from inside the work
├── state sessions that outlive a single call
├── interaction branches that wait for external input
└── control pause, resume, cancel
| You own | AgentDeck owns |
|---|---|
| agents, tools, workflows | Events. One ordered stream of what happened. |
| what progress means | Reporting. Progress and status, sent from inside the work. |
| when work should stop | Control. Execution paused, resumed or cancelled at safe points. |
| when a person decides | Interaction. Branches that wait for external input. |
| business state | State. Sessions that outlive a single call. |
| your UI and integrations | Surfaces. Observers, HTTP/SSE and your UI read the same run. |
The complexity is still there. It just lives in the layer built for it.
Streaming and event logs
Every managed execution produces an immutable, ordered stream of events:
async with deck:
async for event in deck.stream("handle_request", {"id": "T-100", "query": "status update"}):
print(event.kind) # run.started, tool.call.started, text.delta, run.completed
Execution you can steer
A Run is first-class and addressable. Steering methods belong to the handle:
run = await deck.runs.start("handle_request", {"id": "T-100", "query": "status update", "urgent": True})
if run.can.pause:
await run.pause()
await run.resume()
# Answer an execution waiting on human approval:
await run.answer(True)
result = await run
deck.runs.get(id) rehydrates the handle in another process, so a run parked on input or paused by a web request can be resumed by an asynchronous worker.
Where your definitions live
Everything you define can live in a .agentdeck/ directory next to where you run. The path is the registration:
.agentdeck/
├── agents/support_bot/agent.py # an Agent(...)
├── workflows/handle_ticket/workflow.py # a @workflow function
└── skills/troubleshooting/ # SKILL.md + prompt resources
async with Deck.from_project() as deck:
result = await deck.run("handle_ticket", {"id": "T-101", "query": "help"})
Deck.from_project() discovers and validates all definitions at startup, catching missing skills, invalid types, or broken references at build() time.
Who it is for
You want this if you are putting agents somewhere they have to keep working: several agents and workflows in one project, a chat surface and a batch path over the same definitions, runs you need to inspect afterwards, approvals that outlive the process that asked for them.
You do not want this if you are writing one script that calls one model. Use the Agents SDK directly, and come back when the wiring around it has become the work. You also do not want it if you have already built your own harness: AgentDeck is opinionated about project layout and configuration, and those opinions are the product.
What it deliberately does not do
- No DSL. Definitions are Python. There is no YAML agent format, and there will not be one.
- No agent loop of its own. Bugs in the agent loop belong upstream, and improvements there arrive without agentdeck doing anything.
- No sandbox. Tools, skills and workflows are ordinary Python in your process, and a model-chosen tool call is trusted by design. See SECURITY.md before you give an agent something destructive.
- No auth, no multi-tenancy, no hosted control plane, no marketplace.
namespacelabels a run; it does not authenticate anyone. Put a real gateway in front of the HTTP surface. - No evaluation framework or prompt management. Model prefixes select configured providers; AgentDeck does not add a dynamic routing service.
Install
pip install agentdeck-sdk # or, with the HTTP surface: agentdeck-sdk[serve]
export OPENAI_MODEL=gpt-4.1-mini OPENAI_API_KEY=sk-...
The distribution is agentdeck-sdk; the import stays agentdeck. Agents may declare
openai/..., anthropic/..., gemini/..., ollama/..., or openrouter/...; see
model configuration. OPENAI_BASE_URL also
supports any OpenAI-compatible endpoint. Extras: serve for the
HTTP surface, postgres for the Postgres event log, redis for Redis-backed sessions or event
log, observability for Langfuse tracing.
Contributing to agentdeck itself is a different setup: see CONTRIBUTING.md.
Documentation
The full documentation and live assistant demo are at agentdecksdk.com:
- Quickstart: install, configure, first agent.
- Build Your Deck: agents, workflows, skills, tools, context.
- Runs & Control: runs, sessions, events, lifecycle control.
- Reference: every setting and every
Deckmethod, generated from code. - Jack Documentation Agent: a real reference assistant running on the docs site.
- Runnable Examples: chat agents, human approval workflows, and skills.
If AgentDeck is useful to you, a star helps other developers find it.
Project
- Contributing: CONTRIBUTING.md. PRs target
dev;make checkis the gate. - Internals:
agentdeck/README.md. - Brand:
docs/brand/. - Security: SECURITY.md.
- Code of conduct: CODE_OF_CONDUCT.md.
- License: MIT, see LICENSE.
Contributors
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentdeck_sdk-5.0.3.tar.gz.
File metadata
- Download URL: agentdeck_sdk-5.0.3.tar.gz
- Upload date:
- Size: 1.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93d985ffccd928c80ed53c3a81fa7aa56cb2a9a7c35b0b7d216ae92012dc8d0a
|
|
| MD5 |
c74f6457964e0aecf91bbf7edf9cd518
|
|
| BLAKE2b-256 |
277370ec392e12a11faf64a2f610c3af9f55768e515ba9c52737066e0fa33158
|
Provenance
The following attestation bundles were made for agentdeck_sdk-5.0.3.tar.gz:
Publisher:
release.yml on agentdecksdk/agentdeck
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentdeck_sdk-5.0.3.tar.gz -
Subject digest:
93d985ffccd928c80ed53c3a81fa7aa56cb2a9a7c35b0b7d216ae92012dc8d0a - Sigstore transparency entry: 2569030536
- Sigstore integration time:
-
Permalink:
agentdecksdk/agentdeck@7f5672d6151127609417c13a0fbca7c3b8180b99 -
Branch / Tag:
refs/tags/v5.0.3 - Owner: https://github.com/agentdecksdk
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7f5672d6151127609417c13a0fbca7c3b8180b99 -
Trigger Event:
push
-
Statement type:
File details
Details for the file agentdeck_sdk-5.0.3-py3-none-any.whl.
File metadata
- Download URL: agentdeck_sdk-5.0.3-py3-none-any.whl
- Upload date:
- Size: 276.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5eb562d6b99158c0e3d1d8d4bec7d3a22b23e89582544edd7788ffccdfb16c2
|
|
| MD5 |
ec2b82c5fde45b2ffbd7fa4ea525c8bb
|
|
| BLAKE2b-256 |
4127976a2ad661800c5c94144e327ef1886948f0fd9634dcc693b045a84e71bc
|
Provenance
The following attestation bundles were made for agentdeck_sdk-5.0.3-py3-none-any.whl:
Publisher:
release.yml on agentdecksdk/agentdeck
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentdeck_sdk-5.0.3-py3-none-any.whl -
Subject digest:
f5eb562d6b99158c0e3d1d8d4bec7d3a22b23e89582544edd7788ffccdfb16c2 - Sigstore transparency entry: 2569030584
- Sigstore integration time:
-
Permalink:
agentdecksdk/agentdeck@7f5672d6151127609417c13a0fbca7c3b8180b99 -
Branch / Tag:
refs/tags/v5.0.3 - Owner: https://github.com/agentdecksdk
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7f5672d6151127609417c13a0fbca7c3b8180b99 -
Trigger Event:
push
-
Statement type: