The Agentic Page Bar (APB) lets a product agent move counsel around the app — "show my clients" opens the
clients list, "firm members" opens the team page. This Story builds the brain side of that in
pramaan-agents: Atlas's descriptor (who he is on the bar), his page-tool catalog
(the typed intents he can emit), and the route-intent reasoning that maps a natural-language ask onto a
surface — including Hindi. Atlas is the FIRST descriptor; everything else is agent-agnostic so agents
#2-#25 reuse it unchanged.
surface_key + typed params, never a string-built URL, and it holds no execution
credentials. It PROPOSES a typed intent; the frontend executes it. A URL-shaped key is rejected at the
Pydantic boundary, not by convention (RFC-APB-002 §C).| Area | Where | What it does |
|---|---|---|
| Agent-agnostic contracts | agents/atlas/navigation.py | AgentDescriptor + PresenceCopy (en/hi), SurfaceEntry (open shape, typed params_schema, kind), and the page-tool intents NavigateTo / SetFilter / OpenView / Find. URL-rejecting validators live here. |
| The first descriptor (Atlas) | agents/atlas/descriptor.py | The only Atlas-specific file: fills the shapes with Atlas's data — accent="accent.atlas" (a token), presence in en+hi, and ATLAS_PAGE_TOOLS wrapping the existing navigate/filter/view/find capabilities. |
| Route-intent reasoning | agents/atlas/route_intent.py | The single generic navigate_to: a Pydantic AI agent that reads the per-turn availableSurfaces and emits a NavigateTo. An output_validator forbids a key the model wasn't shown. |
| Golden nav-evals | agents/atlas/evals/nav_*.py · nav_cases.jsonl | 7 golden cases incl. 2 Hindi, graded by the deterministic RoutedToExpectedSurface gate over a reference manifest (mirrors ROUTE-REGISTRY.md). No LLM judge — routing is an exact key match. |
| Offline gates (CI) | tests/test_descriptor.py · tests/test_nav_evals.py | 28 no-key tests: descriptor fields, en+hi presence, accent-is-a-token, URL rejection, no credential fields, the routing gate bites, the prompt renders. |
// NavigateTo — a typed route intent (the frontend executes it) { kind: "navigate_to", surface_key: "settings.team", // a stable key, NEVER "/settings/firm/team" params: { matterId: "M-0005" }, // typed route params, strings only anchor: null } // optional sub-section/tab // SurfaceEntry — injected per turn from the frontend manifest (brain keeps no catalog) { key:"clients", description:"The list of the firm's clients…", // the model reasons over THIS capabilities:[…], kind:"route", level:"l1", params_schema:{…} } // open shape (extra=allow)
# 1. offline gates (no key — runs in CI) cd agents/atlas && pytest tests/test_descriptor.py tests/test_nav_evals.py -q # 28 passed # 2. golden nav-evals LIVE against the real model (needs OPENROUTER_API_KEY) cd agents/atlas && python -m evals.nav_run
Live run on DeepSeek v3.2 (OpenRouter): 100% ✔ (7/7). The two RFC English goldens
("show my clients"→clients, "firm members"→settings.team) and both Hindi prompts
(मेरे मुवक्किल दिखाओ→clients, मेरी फर्म के सदस्य दिखाओ→settings.team) routed correctly —
proving Hindi intent maps onto the English reasoning descriptions.
presenceKey carries en+hi; accent is a token (literal colours rejected).navigate_to via surface_key + typed params, never raw URLs (validated).pramaan-agents).descriptor.py is agent-agnostic; the surface manifest is injected per turn, not a brain-side catalog (RFC-APB-002 Q4).navigate_to into main.py + the broker injecting availableSurfaces per turn = downstream Wave-1 tickets. The reference manifest here is a TEST fixture.