Skip to Content
How Jack Is BuiltHow Jack is built

How Jack is built

Jack is the AgentDeck documentation agent running on this site. The same application powers the live experience at the bottom of the home page, and its source is in the repository.

This page shows what building a real application with AgentDeck looks like: what you write, and what you get around it.

The application

Jack answers questions about AgentDeck by reading its documentation.

Question → Jack → search_docs / read_doc / read_changelog → Answer

That shape is the whole application, and the code says the same thing:

from agentdeck import Agent, Context, Deck def search_docs(query: str, docs: Context[DocsCorpus]) -> str: """Find AgentDeck documentation pages matching a query.""" return docs.data.search(query) def read_doc(slug: str, docs: Context[DocsCorpus]) -> str: """Read one AgentDeck documentation page in full, by its slug.""" return docs.data.pages[slug] jack = Agent( name="Jack", instructions=instructions, tools=[search_docs, read_doc, read_changelog], ) deck = Deck(agents=[jack], context=DocsCorpus)

Three ordinary functions, one agent, one Deck. Context[DocsCorpus] is how a tool reaches the application’s own data; the model is offered only query or slug.

The application code stays application code

Almost everything Jack-specific is about what Jack should do: how to search the corpus, how to read a page, what to say when the documentation does not cover something, and how to cite what he used. That is the file you would expect to write.

You write the behavior. Nothing above reaches for a runtime concern, because it does not have to.

AgentDeck provides the system around it

The same small application runs inside a foundation it did not have to build.

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 a person └── control pause, resume, cancel

Around that model, other things connect to the same execution: observers and telemetry, the HTTP and SSE surfaces, and the website itself. They read the run rather than a translation of it, so none of them needs Jack to expose anything special.

Jack did not assemble these. They are what a Deck gives an application the moment it runs.

From execution to the website

The live experience on this site is that model, exposed.

Jack executes through AgentDeck → the run emits canonical events → a surface streams them → the site renders the conversation and the tree beside it

The route is a few lines over deck.stream(), and the wire is the event log itself:

async for event in deck.stream(AGENT, question, context=corpus, session_id=session_id): if event.kind in PUBLIC_KINDS: yield f"data: {event.model_dump_json()}\n\n"

There is no translation layer on either side. The browser switches on event.kind, and so would a Python process reading the same run back tomorrow. The execution tree you see next to Jack is built from those events, in the order they arrived.

See it running

Ask him something on the home page and watch the tree fill as he works: a tool call appears when he makes one, and the run resolves when it completes.

Source

  • examples/jack - the agent, its tools, the corpus and the route
  • Implementation notes - the decisions behind this build, and the alternatives they beat
  • Examples - smaller runnable projects, each exercising a single idea