jeevesagent.graph

Agent structure visualization — Mermaid graph generator.

LangGraph established the de facto pattern: emit a Mermaid text diagram describing the agent’s structure, optionally render it to PNG via mermaid.ink. We follow the same shape, extended to walk our nested architectures and surface tool attachments.

Public surface

  • build_graph() — walk an Agent and return an AgentGraph (nodes + edges + subgraphs).

  • AgentGraph.to_mermaid() — render the graph to Mermaid text.

  • Agent.generate_graph() — high-level convenience that walks the tree, renders, and dispatches to disk by file extension:

    • .mmd — raw Mermaid source

    • .md — Markdown with the diagram in a mermaid fence (renders natively on GitHub, in IDE markdown previews, in Jupyter via IPython.display.Markdown)

    • .png / .svg — fetched from https://mermaid.ink via urllib (no extra deps); falls back to writing .mmd next to the requested path if the network call fails

What’s captured

  • The top-level Agent and its architecture

  • Every sub-agent declared by the architecture’s Architecture.declared_workers()

  • Tool attachments per agent (filesystem tools, custom @tool functions, MCP-bound tools)

  • Architecture-specific structural relationships:

    • Supervisor: coordinator → workers via delegate

    • Router: classifier → routes via classifies

    • Swarm: peer → peer via handoff

    • ActorCritic: actor ⇄ critic loop

    • MultiAgentDebate: debaters → judge

    • Blackboard: agents ↔ shared workspace ↔ decider

    • Reflexion: wraps the base architecture in a retry loop

  • Recursive composition: nested architectures (Reflexion of Supervisor, Supervisor whose worker is itself a Supervisor) render as nested subgraphs.

Design notes

  • Pure stdlib. No httpx / graphviz / playwright dependency. Mermaid is emitted as f-strings; PNG/SVG fetches use urllib.

  • Async, like the rest of the framework, because tool enumeration goes through ToolHost.list_tools() (the MCP path is async).

  • Stable node ids: a deterministic counter prefixed by node kind (a0, a1 for agents, t0, t1 for tools, etc.) so diffing the output across runs is meaningful.

Classes

AgentGraph

Renderable graph of an agent's structure.

Functions

build_graph(→ AgentGraph)

Walk an Agent and return its renderable

write_graph(→ str)

Walk the agent, render to Mermaid, write to path.

Module Contents

class jeevesagent.graph.AgentGraph[source]

Renderable graph of an agent’s structure.

to_mermaid() str[source]

Render to a Mermaid flowchart TB block.

Output is plain Mermaid (no %%{init}%% directives) so it renders consistently across GitHub, IDE previews, and mermaid.ink.

edges: list[_Edge] = []
nodes: list[_Node] = []
subgraphs: list[_Subgraph] = []
title: str = 'Agent'
async jeevesagent.graph.build_graph(agent: jeevesagent.agent.api.Agent, *, title: str = 'Agent') AgentGraph[source]

Walk an Agent and return its renderable AgentGraph.

async jeevesagent.graph.write_graph(agent: jeevesagent.agent.api.Agent, path: str | pathlib.Path, *, title: str | None = None) str[source]

Walk the agent, render to Mermaid, write to path.

Extension dispatch:

  • .mmd — raw Mermaid source

  • .md — Markdown with the diagram in a mermaid fence

  • .png / .svg — fetched from mermaid.ink; on network failure, writes .mmd next to the requested path and returns the Mermaid text anyway

Returns the Mermaid text in every case.