Documentation that re-checks itself every time you merge.
Point it at a repository and get a browsable, cited documentation site — the context your coding agents read before they touch anything. Every merge is watched; pages that go out of date are flagged and re-proposed.
A real page, exactly as served.
This is OpenAI Agents SDK — built from openai/openai-agents-python. Same tree, same prose, same citations you'd get for your own repository. Hover any citation — the verbatim source quote appears, pinned to the commit it was verified at. Click a box in the diagram — the claims it was drawn from appear beneath it.
Run loop internals
The run loop — the core of agent execution — is implemented as a delegation chain: src/agents/run.py orchestrates single turns, guardrails, and streaming by calling internal helpers from run_loop.py, session_persistence.py, and blocked_output.py, which in turn use internal data structures from run_steps.py to track step results and tool categories. ProcessedResponse in run_steps.py categorizes tool calls and approvals into separate lists (handoffs, functions, computer actions, shell calls, patches, MCP requests, interruptions, not-found tools, custom tools) and exports methods to query whether execution or user approval is needed.
src/agents/run.py delegates run-loop mechanics — single-turn execution, guardrail checks, tool execution, and streaming start — to helpers in src/agents/run_internal/run_loop.py via imports such as run_single_turn, run_input_guardrails, run_output_guardrails, and start_streaming.[1] run_loop.py is an internal orchestration module; all symbols it defines are explicitly marked as not part of the public SDK surface.[2] src/agents/run.py delegates session and memory persistence to helpers in src/agents/run_internal/session_persistence.py, including prepare_input_with_session, save_result_to_session, resumed_turn_items, and persist_session_items_for_guardrail_trip.[1] src/agents/run_internal/blocked_output.py manages output-guardrail-blocked scenarios — retaining items, sanitizing guardrail results, and replacing blocked content with a data-free placeholder — and is imported by src/agents/run.py.[1] src/agents/run_internal/run_steps.py defines the internal step and result data structures consumed by the run-loop orchestration; none of these types are part of the public SDK surface.[3]
ProcessedResponse in run_steps.py tracks separate lists for every category of tool call produced by a model turn: handoffs, functions, computer_actions, local_shell_calls, shell_calls, apply_patch_calls, mcp_approval_requests, interruptions, function_tools_not_found, and custom_tool_calls.[3] ProcessedResponse.has_tools_or_approvals_to_run() returns True when any of handoffs, functions, computer_actions, custom_tool_calls, local_shell_calls, shell_calls, apply_patch_calls, mcp_approval_requests, or function_tools_not_found are non-empty; hosted tools are excluded because they have already executed server-side.[3] ProcessedResponse.has_interruptions() returns True when self.interruptions is non-empty, indicating there are tool calls awaiting user approval (human-in-the-loop).[3] ToolRunFunctionNotFound in run_steps.py is a dataclass recording a tool call where the named function was not found; it appears in ProcessedResponse.function_tools_not_found and is counted by has_tools_or_approvals_to_run().[3]
SingleStepResult.generated_items in run_steps.py returns pre_step_items concatenated with session_step_items when set, falling back to new_step_items; session_step_items contains the full unfiltered item list for complete session observability.[3] SingleStepResult.processed_response in run_steps.py preserves the ProcessedResponse from the current step and is explicitly needed for resuming runs from interruptions.[3] SingleStepResult.nested_history_owned_items is None when the step did not rewrite handoff history; a non-None list signals that a handoff replaced history, requiring reconciliation of prior ownership against the new input.[3] NextStepInterruption in run_steps.py carries response_accepted (whether the server already accepted the response whose local processing is incomplete) and llm_end_hooks_started (whether response-end hooks fired before the interruption was persisted).[3]
QueueCompleteSentinel in run_steps.py is a sentinel class used to signal that streaming of run-loop results is finished; a singleton instance QUEUE_COMPLETE_SENTINEL is provided.[3] NOT_FINAL_OUTPUT in run_steps.py is a pre-built ToolsToFinalOutputResult(is_final_output=False, final_output=None) constant used to signal that tool execution did not produce a terminal output.[3] run_loop.py re-exports OUTPUT_GUARDRAIL_BLOCKED_TOOL_OUTPUT from blocked_output under the alias _OUTPUT_GUARDRAIL_BLOCKED_TOOL_OUTPUT.[2]
_prepare_turn_input_items in run_loop.py converts the caller's raw input to a new input list, converts generated RunItems to input items (respecting the reasoning_item_id_policy), then merges the two via prepare_model_input_items.[2] _should_persist_stream_items in run_loop.py skips session persistence when no session is configured or a server-managed conversation tracker is present, and also skips when an input guardrail tripwire was triggered during streaming.[2] cleanup_models_after_run in run_loop.py iterates every model resolved during a run and calls model._cleanup_on_run_end(tool_use_tracker) on each; failures are logged as warnings rather than raised.[2] _ensure_stream_event_item_occurrence_key in run_loop.py lazily assigns a uuid4().hex key to a RunItem if one is not already present, ensuring each streamed item has a stable occurrence identity.[2] _stream_event_item_occurrence_key in run_loop.py retrieves a per-RunItem UUID stored under the attribute _agents_stream_event_item_occurrence_key, returning None if absent or not a non-empty string.[2]
run_loop._retained_items_for_blocked_output is called to rebuild the allowed subset of tool call/output items when an output guardrail blocks a function batch (exercised in tests/test_agent_runner.py).[4] run_loop._retained_items_for_blocked_output guards against hash-collision and equality-impostor attacks on dict-key discriminators: it does not invoke __eq__ on non-string keys, and if EqualityImpostor.__eq__ returns True for discriminator fields the entire batch is discarded rather than accepted.[4] When the caller is a valid CallerDirect, the caller field is preserved in the retained ToolCallItem's raw_item as {"type": "direct"}.[4]
tests/test_agent_runner.py imports and exercises a wide range of internal helpers — including run_loop._retained_items_for_blocked_output, drop_orphan_function_calls, normalize_input_items_for_api, persist_session_items_for_guardrail_trip, save_result_to_session, and execute_approved_tools — confirming these are testable internal contracts.[4]
Sources
Popular repositories, already documented.
Open one and read the tree before you connect anything of your own. Every page carries the commit it was verified at.
Living documentation for openai/openai-agents-python — auto-built from the source and kept current by a daily watcher.
Living documentation for anthropics/anthropic-sdk-python — auto-built from the source and kept current by a daily watcher.
Living documentation for cloudflare/cloudflare-os — auto-built from the source and kept current by a daily watcher.
How docs get built, and stay built
The Codebase docs template scaffolds architecture, modules, public APIs and a decisions log, then attaches the watcher that keeps them current.
The merge that invalidates a page is the moment the page gets fixed.
When a merge touches code a page was derived from, that page is marked stale and a rewrite is proposed with the diff that caused it. Diagrams keep score the same way — when the claims behind a drawing change, the figure says so and can be redrawn on demand. Nothing is published over your prose without review.
See it on a public repoAI writes more of your codebase every week. Understanding it is the new bottleneck.
Agents ship code faster than any team can read it — the hard part is no longer making the change, it's knowing what your system does after a hundred of them. Living documentation is how you keep up: every merge is re-checked and explained, so the shape of the codebase stays visible as it shifts. And the same pages are the context your agents read before their next change — the docs are both the record of what AI did and the input to what it does next.