Skip to content

Ground an Agent in Your Company Handbook

Maya runs the internal-tools team. The company handbook is a folder of policies, onboarding guides, and contracts — hundreds of files across dozens of folders. Her first attempt at a “handbook bot” was the usual recipe: a loader, a text splitter, an embedder, a vector store, glued together by hand. It answered confidently and often wrongly, with no way to show where an answer came from.

The problem wasn’t the model. It was that her pipeline flattened the handbook into a pile of disconnected chunks. The folder structure — policies/data/ vs contracts/2024/ — and the links between documents were thrown away before the model ever saw them.

A retrieval agent that:

  • Answers questions from the handbook and cites the source file every time.
  • Knows the shape of the handbook — document types, folders, and cross-references.
  • Took one build command and one connect() call to wire up.

By the end you’ll have a handbook.indx archive and an agent that reads from it.

  1. Install indx and a framework adapter.

    The connectors live behind extras so the core stays light. Maya uses the OpenAI Agents SDK, but every framework is one method call — pick yours.

    Terminal window
    pip install "indx[cloud]" "indx[openai-agents]"
    export OPENAI_API_KEY="sk-..."
  2. Build the knowledge space from the handbook folder.

    The directory is the input. indx walks the tree, parses each file, chunks it, derives the relationship graph, enriches each document with a type and summary, and embeds everything — then seals it into one portable archive.

    Terminal window
    indx ./handbook --out ./ai-ready
    indx ./handbook → ./ai-ready
    01 walk 142 files, 18 folders
    02 parse 142 ok, 0 skipped
    03 chunk 1180 chunks
    04 relate 412 relations
    05 enrich 142 documents (openai:gpt-5-mini)
    06 embed 1180 vectors → qdrant, sealed handbook.indx
    done: 1180 chunks, 142 docs, embed_dim=1536 (14.1s)

    That 04 relate 412 relations line is the part a hand-rolled pipeline never had: sibling, parent, and references edges that carry the handbook’s structure into retrieval.

  3. Sanity-check retrieval before writing any agent code.

    Never wire an agent to a space you haven’t looked at. Query it from the terminal first.

    Terminal window
    indx query ./ai-ready/handbook.indx "how long do we retain customer data?" -k 3
    #1 score 0.84 policies/data/retention.pdf (policies/data · policy)
    "Customer data is retained for 90 days, after which it is purged…"
    neighbors: chunk_0203, chunk_0205

    The hit comes back with its source path, its detected type (policy), and neighbor chunk ids for context. That provenance is exactly what your agent will cite.

  4. Plug the space into your agent — one call.

    connect() loads the archive and hands your framework native tools. No indx types leak into your agent code.

    from agents import Agent, Runner
    from indx.agent import connect
    kb = connect("ai-ready/handbook.indx", name="company-handbook")
    agent = Agent(
    name="Handbook",
    instructions="Answer only from the handbook tools. Always cite the source path.",
    tools=kb.openai(),
    )
    result = Runner.run_sync(agent, "How long do we retain customer data? Cite the source.")
    print(result.final_output)

    The agent now has three tools — indx_search, indx_overview, and indx_get_document — the same retrieval path you tested in step 3.

  5. Read a grounded, cited answer.

    We retain customer data for 90 days, after which it is automatically purged.
    Source: policies/data/retention.pdf (policy)

    The citation is real: it’s the hit.source.path the search tool returned, not something the model invented.

Maya’s hand-rolled pipeline retrieved text. The indx space retrieves grounded text — every chunk carries its source document, folder, detected type, and neighbor links.

That changes what the agent can do:

  • It cites. Every hit has a source.path, so “where did this come from?” always has an answer.
  • It can filter by structure. Ask it to restrict to one document type and it can — kb.search(query, k=5, doc_type="policy") only returns policies.
  • It can widen context. Pass with_context=True to connect() and each hit carries its neighbor chunks, so the model reads around a match instead of seeing an orphaned fragment.
kb = connect("ai-ready/handbook.indx", default_k=8, with_context=True)
  • A directory becomes a queryable, cited knowledge space with one build command.
  • connect() turns that archive into native tools for any framework — one object, one method per framework.
  • Provenance (source.path, type, neighbors) is what makes grounded RAG trustworthy, and indx keeps it end to end.