Skip to main content
AgentDeck

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.

CI Release Python License Docs

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 @tool decorators. Tools declare ToolCtx[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. Use WorkflowCtx to invoke targets (ctx.invoke), branch in parallel (ctx.parallel), or park for human input (ctx.ask).
  • Decks assemble applications: Deck is 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. namespace labels 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:

If AgentDeck is useful to you, a star helps other developers find it.


Project

Contributors

Contributors

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agentdeck_sdk-5.0.3.tar.gz (1.4 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agentdeck_sdk-5.0.3-py3-none-any.whl (276.8 kB view details)

Uploaded Python 3

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

Hashes for agentdeck_sdk-5.0.3.tar.gz
Algorithm Hash digest
SHA256 93d985ffccd928c80ed53c3a81fa7aa56cb2a9a7c35b0b7d216ae92012dc8d0a
MD5 c74f6457964e0aecf91bbf7edf9cd518
BLAKE2b-256 277370ec392e12a11faf64a2f610c3af9f55768e515ba9c52737066e0fa33158

See more details on using hashes here.

Provenance

The following attestation bundles were made for agentdeck_sdk-5.0.3.tar.gz:

Publisher: release.yml on agentdecksdk/agentdeck

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for agentdeck_sdk-5.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 f5eb562d6b99158c0e3d1d8d4bec7d3a22b23e89582544edd7788ffccdfb16c2
MD5 ec2b82c5fde45b2ffbd7fa4ea525c8bb
BLAKE2b-256 4127976a2ad661800c5c94144e327ef1886948f0fd9634dcc693b045a84e71bc

See more details on using hashes here.

Provenance

The following attestation bundles were made for agentdeck_sdk-5.0.3-py3-none-any.whl:

Publisher: release.yml on agentdecksdk/agentdeck

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

5.0.3 This release

2 files

5.0.0

2 files

4.0.5

2 files

4.0.4

2 files

4.0.3

2 files

4.0.2

2 files

4.0.1

2 files

4.0.0

2 files

3.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page