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:

ConfigurationResponsibility
content_dbContent metadata and synchronization bookkeeping
page_storePublished Markdown in a namespaced FileSystem
vector_dbPgVector 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

ToolPurpose
search_docsSearch with the caller's alternative phrasings and return ranked evidence
query_docs_filesystemRead pages and find exact text through PageFileSystem commands
submit_docs_feedbackRecord 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.