AI-assisted Development / Article

Understand an AI Agent's Code with Architecture and Sequence Diagrams

Investigate a fictional release-note agent by connecting its model loop, read tools, and draft storage to code evidence and one concrete scenario.

Shared case study: A release-note agent

An agent can look simple at the entry point: send a prompt, run a tool, repeat. The behavior that matters often lives elsewhere: which tools are available, who checks permissions, where state survives a restart, and what happens after a network response disappears.

To understand an unfamiliar agent repository, build two connected explanations. Use an architecture view to identify responsibilities and boundaries. Use a sequence to explain one request through those same participants. The result should help you choose where to investigate or change code, with evidence for each claim.

Choose one observable outcome

Consider a fictional release-note agent. A maintainer asks it to summarize merged changes. It can read repository metadata, call a language model, and save a draft. A separate publication request sends the draft to a release host. This example is a teaching system, not a description of Unograph's implementation.

Start with a question small enough to answer: What happens between requesting a draft and seeing a saved revision? Leave publication for a second trace. Otherwise, a diagram can become a tour of every package instead of an explanation of behavior.

Find the entry handler, the runner it invokes, the tool registry, the persistence adapter, and a test exercising that path. Read configuration as well as functions: a tool implemented in the repository may be unavailable to this particular agent.

Map responsibilities, not directories

The useful participants in the example are a Release Console, Agent Runner, Repository Adapter, Draft Store, external Language Model, and external Repository Host. The Publication Gateway and Release Host belong on the wider map, but are outside the draft-generation scenario.

Label connections with verbs. The runner requests model output, the adapter reads merged changes, and the store persists draft revisions. A label such as “uses” leaves the important question unanswered: can this connection read, write, or both? At the repository boundary, identify the target data and error contract as well; KitDesk's Adapter lesson shows why translating an API means more than renaming its methods.

These are logical responsibilities. They need not be separate services. If the runner and adapter are modules in one process, show that boundary explicitly rather than implying a network hop. C4's component diagram guidance similarly focuses on responsibilities inside a container. Use the amount of detail that answers your question. Fieldnote's ownership and trust boundaries also help distinguish who operates a component from which inputs it may trust.

Illustrative evidence notes for the release-note agent
Model claimEvidence to locate in your repositoryUncertainty to resolve
The runner can read merged changesTool registration and the adapter call siteWhich repositories and fields are allowed?
A draft survives the requestStore write and a persistence testDoes it survive a process restart?
The model cannot directly publishActive tool allowlist and gateway authorizationIs another execution path able to bypass this boundary?

Replace these evidence descriptions with real paths, symbols, tests, and a commit identifier during a repository investigation. An arrow inferred from a filename is a hypothesis until a call site or observation supports it.

Live model · Architecture view

Read the agent's responsibilities and generation path

The shared model separates the Agent Runner, Repository Adapter, persistent store, and external Language Model. The draft-generation sequence shows application-controlled tool dispatch and where a revision is saved.

Follow a repository read from the runner to the repository host and back, then locate the step that persists the draft revision. Open the public diagram ↗
Explore scenarios in this model

These links open the same public model in a selected view. They do not change its source.

Open this viewer on its own ↗ if the frame is unavailable. The explanation remains readable without the viewer.

Exploration is local to your viewer. Reload or Reset view returns to the source layout.

Trace the loop and its limits

A simplified runner might behave like this. This is explanatory pseudocode; it omits validation, errors, and provider-specific response formats.

for step in range(step_limit):
    response = model.respond(messages, tools=read_tools)
    if response.requests_tool:
        result = dispatch_allowed_tool(response.tool_request)
        messages.append(tool_result(result))
    else:
        return drafts.save_new_revision(response.text)
raise StepLimitReached()

Follow an actual test or a redacted development trace. The console requests a draft. The runner calls the model. The model requests repository data. The runner validates and dispatches that request through the adapter, adds the result to the conversation, and calls the model again. A final response becomes a persisted draft revision.

The model proposes a tool call; application code decides whether and how to execute it. Keep those steps separate in the sequence. Also show where the loop stops. A retry limit, cancellation, and a maximum number of tool turns are distinct controls.

Do not assume every application called an “agent” follows this pattern. Anthropic's Building effective agents distinguishes predefined workflows from systems in which a model directs its tool use. Classify the code you find before choosing a diagram shape. Its 2024 article is useful for that distinction, not a current inventory of available tooling.

Live model · Sequence view

Follow the bounded generation loop

The generation scenario gives the architecture a concrete order. The language model proposes a repository-read tool call; the runner validates and dispatches it, then saves a draft revision. Publication is outside this read-only tool loop.

Trace a read request and its return, then find the saved revision. Identify where application code, rather than the model response, owns dispatch and the turn budget. Open the public diagram ↗

Open this viewer on its own ↗ if the frame is unavailable. The explanation remains readable without the viewer.

Use disagreement to find the next question

Suppose the architecture says “maintainer approves publication,” but the publication handler receives only a draft ID and loads its latest text. The sequence exposes a missing detail: which revision did the maintainer see? The diagram has found an investigation target, not proved that the implementation is defective. Check the handler, store semantics, and tests before drawing a conclusion.

A static map cannot establish call order. A single sequence cannot establish all possible behavior. A trace shows one execution, including only the events you recorded. Reading all three together is useful precisely because they have different limits.

Avoid mapping every helper function. That creates a second code listing that becomes expensive to maintain. Add a participant when it owns state, a policy decision, or a boundary relevant to the question.

Try it in Unograph

Open Unograph and model the runner, repository adapter, and draft store as distinct responsibilities. Reuse those elements in a draft-generation sequence. Follow the repository read from the runner to the host and back; then find the step that saves the revision. Record one uncertain claim in your investigation notes and identify the code or test that could resolve it.

You are finished when you can explain one outcome, point to supporting evidence, and name what the model leaves out. Next, use that understanding in Write a Diagram-Driven Brief for an AI Coding Agent. The release-note agent learning path connects this investigation to briefing, failure analysis, implementation, and maintenance.