How We Built the Agno Docs Agent
Published pages, explicit retrieval, citations, and public serving in Docs Agent v2.
The Agno Docs Agent powers documentation chat and exposes the same retrieval tools through MCP. Its v2 implementation is a small application over Agno's published-page and public-serving APIs. The application owns the prompt, retrieval policy, citations, feedback, and deployment settings.
This walkthrough follows the v2 implementation.
Publish one source of documentation
The sync workflow discovers pages from the deployed site's llms.txt and its sub-indexes, then fetches clean Markdown. It normalizes the site's remaining MDX presentation elements before publishing pages.
The Knowledge configuration combines three stores in the same PostgreSQL database:
| Configuration | Responsibility |
|---|---|
content_db | Content metadata and synchronization bookkeeping |
page_store | Published Markdown in a namespaced FileSystem |
vector_db | PgVector search over the published chunks |
Agno prepares a complete page generation before replacing its Markdown and vectors in one transaction. A namespace lock serializes syncs; individual pages can fail without replacing their previous published generation. The workflow checks the sync report and reports a partial sync as unsuccessful.
Sync runs after a documentation deployment. It is a typed AgentOS workflow with durable background execution, and callers use the configured internal service token. There is no periodic indexing scheduler in this application.
See the source for Knowledge configuration and the sync workflow.
Retrieve before the first model call
The initial retrieval is an explicit callable dependency. Agno supplies the current run input and loaded session; the function searches the current question and, when available, the previous question and their combination.
This excerpt shows the placement in the agent configuration:
# get_docs_context and INSTRUCTIONS are defined by the application.
docs_agent = Agent(
id="docs-agent",
dependencies={"docs_context": get_docs_context},
add_dependencies_to_context=False,
instructions=INSTRUCTIONS,
# Model, database, tools, and history settings omitted here.
)The instructions contain a {docs_context} placeholder inside a search_results block. This gives the model evidence on its first call while keeping the retrieval decision in application code. The function is asynchronous, so requests use Agno's async run path.
Search is a shared pipeline for chat and MCP. The caller can provide alternative phrasings; search embeds and ranks those phrasings without asking another language model to rewrite the query. The application adapts the public page-search result to its tool response format and output budget.
Expand results without mixing revisions
The renderer groups hits by page and tries to read complete pages using the revision returned by search. It includes full pages while they fit within a 24,000-character selection budget, then falls back to the retrieved excerpts. Wrappers and fallback excerpts can exceed that selection budget; it is not a token limit.
If the requested page revision is unavailable, the renderer keeps the original search excerpts and tells the model that expansion was unavailable. It does not silently combine an older search hit with a different published page.
The agent implementation contains both the dependency and this renderer. See Agent dependencies for the underlying API.
Give the agent three explicit tools
| Tool | Purpose |
|---|---|
search_docs | Search with the caller's alternative phrasings and return ranked evidence |
query_docs_filesystem | Read pages and find exact text through PageFileSystem commands |
submit_docs_feedback | Record a report about an incorrect or confusing documentation page |
The filesystem tool offers commands such as rg, head, and cat over published pages. It is a bounded command interpreter, with no operating-system shell or write access. Feedback is the one tool that writes application data.
The prompt tells the agent to answer from retrieved documentation, cite only pages it used, and put numbered Markdown links beside supported claims. It also requires a final Sources: line with the same canonical URLs. These are application instructions, reinforced by evaluation cases and citation scorers; retrieval alone does not guarantee a grounded answer.
Expose those tools through MCP
The AgentOS entrypoint publishes the same three functions:
mcp=MCPConfig(
tools=DOCS_TOOLS,
default_tools=False,
lifecycle_tools=False,
stateless=True,
instructions=SERVER_INSTRUCTIONS,
version=SERVER_VERSION,
allowed_hosts=MCP_ALLOWED_HOSTS,
)Server instructions explain how clients should use the retrieval tools. Disabling built-in and lifecycle tools keeps this MCP server focused on documentation. Stateless transport allows requests to reach different replicas without requiring an MCP session on one process; shared application data still lives in PostgreSQL.
Bound the public service
In production, PublicSurface selects the docs agent, protected sync workflow, and MCP surface. It provides shared PostgreSQL admission limits and bounds request bodies, output, execution time, and active runs. The application supplies its own client-identity function and browser-origin policy for the deployment.
The public agent roster contains only its ID, name, and description. The full administrative API is not exposed through this surface. The sync workflow requires verified credentials; knowing its URL does not allow an anonymous caller to trigger it.
The public configuration trusts Railway's overwritten edge IP header. That deployment-specific choice should be reviewed before reusing the application behind another proxy. See Public Surface for the framework contract.
Check retrieval and answers separately
The application's evaluations check the search pipeline against expected pages, then run agent cases with answer and citation scoring. Unit and database tests cover the adapters, indexing, public requests, and sync behavior. These checks make changes to retrieval and prompting measurable without treating one good chat response as a release test.
The Docs Agent template is coming soon. The walkthrough explains the implementation today; the template will provide a starting point for adapting it to your documentation.