The Atlas descriptor & route-intent

How an agent learns to drive the workspace — typed intents only, never a raw URL.
Story-1653 · Epic-1646 (Agentic Page Bar) · Wave-1 · branch issue-1653-atlas-descriptor-tools · 2026-06-23

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.

The one rule that shapes every type here: the brain addresses surfaces by a stable 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).

What to review

AreaWhereWhat it does
Agent-agnostic contractsagents/atlas/navigation.pyAgentDescriptor + 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.pyThe 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 reasoningagents/atlas/route_intent.pyThe 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-evalsagents/atlas/evals/nav_*.py · nav_cases.jsonl7 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.py28 no-key tests: descriptor fields, en+hi presence, accent-is-a-token, URL rejection, no credential fields, the routing gate bites, the prompt renders.

The contract the brain emits

// 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)

How to verify

# 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.

Acceptance criteria — held

Scope & boundaries honoured