Discovery Surface Projection

AGLedger publishes four discovery surfaces an agent can read with no auth. Your registered schema appears in some of them, and you control specific knobs.

The surfaces

| Path | Format | What it carries | |------|--------|-----------------| | GET /llms.txt | Markdown | Curated link-index optimized for LLM ingestion. Points at the engine's authoritative routes plus an Agent Grounding Directive. | | GET /llms-full.txt | Markdown | Same shape as /llms.txt, with worked code examples inline. Kept separate so the link-index stays terse. | | GET /openapi.json | OpenAPI 3.1 | Full machine-readable spec. Source of truth for route shapes and response schemas. | | GET /.well-known/agent-card.json | A2A 1.0 | Agent Card describing the engine as an A2A-speakable agent (skills, capabilities, transport, supported intents). | | GET /v1/scope-profiles | JSON | Unauthenticated profile catalogue — agents discover their permission envelope here. |

All five are unauthenticated and always-on. None of them rate-limit, gate behind feature flags, or require API keys. An agent that cannot reach any of these has no diagnostic signal — predictable availability is the load-bearing property.

Customer-controlled vs engine-filled

What your registered schema causes to appear in /llms.txt, and what you can override:

| Surface bit | Customer controls | Engine fills | |---|---|---| | Schema title + description in the "Available Types" section | Yes — values from POST /v1/schemas | — | | Custom prepended / appended sections | Yes — _PREPEND_PATH / _APPEND_PATH | — | | Whole-file replacement | Yes — _OVERRIDE_PATH (skips generation) | — | | Section omission | Yes — _OMIT_SECTIONS | — | | Route enumeration in OpenAPI | — | At boot, from the route table | | Scope projection in /v1/scope-profiles | — | At boot, from the authority declaration | | Agent Grounding Directive in /llms.txt | — | Load-bearing — cannot be omitted | | Version footer | — | Cannot be omitted | | Federation signing scheme section | — | Auto-shown only in hub mode |

The engine fills the structural pieces; you tune the content surface that customers expect to vary across deployments.

The Agent Grounding Directive

Every /llms.txt body opens with a directive block. It tells agents to ground decisions in the response body, not in the static doc:

## Agent Grounding Directive

**Ground every decision in the response body, not in this document.** This file
is an index of endpoints and conventions — it is not authoritative for which
action, status, or transition is valid on a specific resource right now.

- Every record response includes `status`, `nextActions`, `validTransitions`,
  and `nextSteps`. Always read `nextSteps` to find the next call — `nextActions`
  only covers /transition verbs and an empty `nextActions` is normal, not a
  stuck state.
- On a 400 error, read `hint`, `suggestion`, `recoveryHint`, and `allowedValues`.
- On a 422 error, read `currentState`, `allowedActions`, `recoveryHint`, and
  `refreshUrl`.
- On a 429, honor `retryAfterSeconds`.

This directive is engine-filled and cannot be omitted. It steers agent behavior at session start: "read the body fields, not this doc." Static enums in a Markdown file go stale; response-body fields cannot.

The four /llms.txt environment variables

When each is the right tool:

Omittable section keys

The canonical set, lifted from LLMS_TXT_OMITTABLE_SECTIONS in src/modules/discovery/llms-txt.ts:

| Key | What it omits | |-----|---| | a2a | Agent-to-Agent Records section + Agent Discovery Endpoints bullet | | proposals | Agent-to-Agent (Proposals) sub-list under Key Endpoints | | delegation | Delegation (sub-records) sub-list — parentRecordId, /chain, /sub-records, /graph, cascade settlement | | disputes | Disputes sub-list under Key Endpoints | | schema-management | Schema Management sub-list | | audit-compliance | Compliance & Audit section | | audit-integrity | Audit Chain Integrity section — chainIntegrity semantics, tamper-detection layers, offline verifier | | webhooks | Webhooks section — subscribe, event types, DLQ, retries, circuit breaker, SSRF rules | | encrypted-records | Encrypted Records section — operatingMode='encrypted' envelope shape | | verification-keys | Verification Keys section | | federation | Federation Signing Scheme section (already auto-hidden outside hub mode) | | a2a-agent-card | A2A Agent Card footer | | optional | Optional self-reference to llms-full.txt | | agent-directory | Agent Directory peer-discovery list |

The Agent Grounding Directive and the Version sections are NOT in this list and cannot be omitted — both are load-bearing. The directive tells agents to read response-body fields rather than infer from static docs; the version footer keeps signature snapshots stable.

Worked example

Register a custom contract type:

curl -X POST "$API_BASE/v1/schemas" \
  -H "Authorization: Bearer $SCHEMA_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "DELIVERY-ATTEMPT-v1",
    "displayName": "Delivery Attempt",
    "description": "Notarize a single delivery attempt by a logistics agent.",
    "recordSchema": {
      "type": "object",
      "required": ["expected_count"],
      "properties": { "expected_count": { "type": "integer", "minimum": 1 } },
      "additionalProperties": false
    }
  }'

The "Available Types" section of /llms.txt now includes:

### DELIVERY-ATTEMPT-v1
Delivery Attempt — Notarize a single delivery attempt by a logistics agent.

/openapi.json components.schemas now contains a generated entry for the type's criteria shape.

Side-by-side: what you sent (one POST), what the agent reads (two surfaces, both auto-updated, no SDK release).

Cache busting

A schema change fires a Postgres LISTEN/NOTIFY and busts the in-process cache; the next read regenerates and serves fresh bytes.

To force-bust without a schema change:

curl -X POST "$API_BASE/v1/admin/discovery/reload" \
  -H "Authorization: Bearer $PLATFORM_KEY"

Operational bounds:

See also


Validated against the live API (v0.22.18) on 2026-05-02.