# Discovery Contract `omni-cli discovery` is the machine-readable contract between the CLI and the agent: what platforms exist, what actions they carry, and exactly how to call each one. It always emits JSON — no `--json` flag needed — and it is tiered so an agent loads only what it needs. ## Three tiers Per-action schemas are heavy; an agent rarely needs more than one at a time. Discovery splits the surface so the always-loaded top level stays small and the full schema arrives only when the agent drills into the action it intends to run. ``` omni-cli discovery # tier 1: platform index omni-cli discovery # tier 2: that platform's actions omni-cli discovery # tier 3: one action in full ``` ### Tier 1 — platform index Platform headers only, no actions. Each entry carries pre-computed `action_count` and `mutating_count` so the agent reads totals instead of aggregating tier-2 responses itself. ```json { "discovery_schema_version": "2.2.0", "authenticated": true, "definition_id": "def_8f3a…", "platforms": [ { "key": "github", "display_name": "GitHub", "host_required": false, "action_count": 21, "mutating_count": 8 }, { "key": "jira", "display_name": "Jira", "host_required": true, "action_count": 14, "mutating_count": 6 } ], "invocation": { "…": "…" }, "global_flags": [ "…" ], "envelope": { "…": "…" }, "pagination": { "…": "…" }, "auth": { "…": "…" }, "context": { "contexts": ["work", "personal"], "current": "work", "source": "default", "status_command": "omni-cli context status --json", "note": "…" }, "operational_commands": ["context", "definitions", "version", "errors", "discovery"], "human_only": { "…": "…" }, "errors": [ "…" ] } ``` ### Tier 2 — one platform's action list Just enough to pick an action: `id`, `argv`, `summary`, `mutating`, `tier_min`. No params, no output schemas. ```json { "platform": { "key": "github", "display_name": "GitHub", "host_required": false }, "actions": [ { "id": "issue.list", "argv": ["github", "issue", "list"], "summary": "List or filter issues.", "mutating": false, "tier_min": "free" }, { "id": "issue.create", "argv": ["github", "issue", "create"], "summary": "Open a new issue.", "mutating": true, "tier_min": "free" } ], "…scaffolding blocks as in tier 1…": {} } ``` ### Tier 3 — one action in full Everything needed to invoke and parse: `params` (the input), `output_schema` (the output), `mutating`/`idempotent`/`tier_min`/`interactive`, plus `pagination` and `order` when the action pages or sorts, a `host` block on host-required platforms, and a ready-to-run `example_invocation`. ```json { "platform": { "key": "github", "display_name": "GitHub", "host_required": false }, "action": { "id": "issue.list", "resource": "issue", "verb": "list", "summary": "List or filter issues.", "argv": ["github", "issue", "list"], "params": [ { "name": "repo", "type": "string", "required": true, "description": "owner/name repository slug.", "example": "octo/hello" }, { "name": "state", "type": "enum", "required": false, "values": ["open", "closed", "all"], "description": "Filter by state." } ], "output_schema": { "type": "array", "items": { "…": "…" } }, "mutating": false, "idempotent": true, "tier_min": "free", "interactive": false, "pagination": { "cursor_param": "page", "next": { "from": "header", "header": "Link", "rel": "next" } }, "example_invocation": "omni-cli github issue list --repo octo/hello --json" }, "…scaffolding blocks as in tier 1…": {} } ``` `example_invocation` is assembled only from the declared examples of the action's required params — if any required param lacks one, the field is omitted rather than invented. An example that lies is worse than none. ## Scaffolding on every response Every tier — and every gated response below — carries the same scaffolding blocks, so any single discovery call is self-sufficient: - `invocation` — the command grammar, flag binding, and host rules (see [Invocation & Envelope](https://omnicli.io/docs/invocation-and-envelope.md)) - `global_flags` — `--context`, `--json`, `--verbose` - `envelope` — the output contract and retry rule - `pagination` — the single-page rule and how to advance - `auth` — authentication is human-only, and (when signed in) which contexts already hold a credential per platform - `context` — which contexts exist (`work`, `personal`), the one that resolves for the current invocation (`current`, `null` when none does, with `source` naming the step of the [resolution chain](https://omnicli.io/docs/contexts.md) that won), and the command to re-check (`omni-cli context status --json`); per-context login state stays in `auth` - `operational_commands` — the agent-runnable commands: `context`, `definitions`, `version`, `errors`, `discovery` - `human_only` — `login`, `logout`, `account`, `self-update`, each with the remedy a human follows - `errors` — the full [exit-code catalog](https://omnicli.io/docs/exit-codes.md) ## Schema versioning `discovery_schema_version` (currently `2.2.0`) versions the JSON shape itself, independently of the binary version. It bumps on any breaking change to the discovery format, so a consumer detects contract changes without diffing binaries. The binary's own version lives under `omni-cli version`. ## Logged out or expired Discovery never goes dark. When there is no account session — or the definition's entitlement has expired — the platform surface and `definition_id` are omitted, but all scaffolding still ships, so an agent can learn how to direct a human to sign in. A top-level `message` and `remedy` distinguish the two states: not signed in (`omni-cli account login`) vs. expired (`omni-cli account status`). A gated drill-down is acknowledged, not answered: the response echoes what was asked via `requested` and `unavailable` (exit 0), without validating the names against the hidden catalog. ```json { "discovery_schema_version": "2.2.0", "authenticated": false, "message": "not authenticated — log in to list your definition's platforms and actions", "remedy": "omni-cli account login", "requested": { "platform": "github", "action": "issue.list" }, "unavailable": "platform detail requires login", "…scaffolding blocks as in tier 1…": {} } ``` ## Unknown platform or action When signed in, a drill-down into a platform or action that doesn't exist fails with exit 2 (`usage_error`) and a remedy listing the valid options — an unknown platform lists the available platform keys; an unknown action points at `omni-cli discovery ` to recover the valid ids. The agent self-corrects without a second guess.