Agent V1 API

Agent Operations V1 (unyolo.io/agent/v1) is the authenticated surface agents use to submit and resume typed provider operations without receiving the provider credential. The canonical contract is protocol/openapi/agent-v1.yaml, with generated Go clients and Echo interfaces under protocol/agentwire/.

The shared contract owns identity, idempotency, lifecycle, presentation, and safe errors. Providers own target, argument, execution, and result validation.

Routes

GET  /healthz

GET  /.well-known/unyolo-agent
POST /api/agent/v1/operations
GET  /api/agent/v1/operations/{id}
GET  /api/agent/v1/operations/{id}/events
POST /api/agent/v1/operations/{id}/cancel
POST /api/agent/v1/sealed-payloads
POST /api/agent/v1/streams
GET  /api/agent/v1/streams/{id}

POST /api/grants
GET  /api/grants
GET  /api/grants/{id}

GET /healthz is the only unauthenticated route. Everything else requires the broker client secret as a bearer token.

Provider surfaces add their own protocol routes on top. gh-broker adds smart-HTTP and LFS paths plus POST /webhooks/github; hf-broker adds GET /v1/models and POST /v1/chat/completions for Router inference. Discrete JSON operations always go through Agent V1, and there are no direct repository-list or contents proxy routes.

Discovery

GET /.well-known/unyolo-agent returns the exact generated contract digest and build identity. Clients compare that digest to detect protocol drift without logging response bodies.

A version label alone is never treated as compatibility evidence.

Handles

HandleMeaning
idempotency_keyExact admission and retry identity. Exposed by MCP as request_id.
operation_idDurable operation lifecycle identity.
approval_idInternal approval linkage. Not exposed by MCP.
transfer_idBounded stream correlation handle.
credential_slotEncrypted destination for generated credentials.

Supplying the same idempotency key with the same immutable request returns the existing operation. Supplying it with a conflicting request returns a bounded conflict rather than creating a second execution.

Submission

Submission returns immediately with the transcript-safe operation: its ID, request ID, state, revision, timestamps, and safe presentation. It never waits for approval.

Authorization happens inside this one lifecycle. A static allow executes immediately and creates no approval state. A matching active window grant authorizes the stored operation and reserves one use atomically. A request effect with no active grant creates one approval linked to that operation. A deny makes no provider request.

Lifecycle and recovery

gh-broker operation get    <id>
gh-broker operation wait   <id>
gh-broker operation cancel <id>

GET /api/agent/v1/operations/{id}/events streams lifecycle events for that operation.

Cancellation is requester-owned. Only the authenticated requester may cancel its own pending request, and a canceled request stays a distinct terminal state so audit records show it was withdrawn rather than refused. Operators deny pending requests and revoke active grants through Operator V1 instead.

Transfers

POST /api/agent/v1/sealed-payloads accepts a bounded authenticated sealed payload. POST /api/agent/v1/streams and GET /api/agent/v1/streams/{id} move bounded stream content with a transfer_id correlating the two halves. Both are authenticated and scoped to the calling client’s own work.

Admission

Submission passes through the admission controller before any durable operation or approval notification is created. Authentication, request validation, and idempotent replay all happen before quota charging, so a correct retry does not consume a slot.

A refusal returns a stable 429 with Retry-After, creates no operation, and does not consume another slot. Cancellation, operator decisions, liveness, and readiness bypass submission admission and stay available during overload.

Defaults are 60 submissions per client per minute, 25 active and 10 pending operations per client, 512 active operations globally, and 64 executing globally. See admission control.

Errors

Errors reduce to a closed set of broker-owned codes before either logs or metric labels see them:

authentication  authorization  canceled   conflict
invalid_response  rate_limited  rejected   storage
timeout           unavailable   other

Provider error text is sanitized before it reaches a client. gh-broker parses GitHub’s documented error message fields, removes control characters, redacts credential-like values, and limits the length. Raw response bodies, GraphQL paths, and extensions are not retained. Sealed operations omit provider messages entirely, because a provider may echo request values back.

Ambiguous completions are never retried automatically. Authority is retained for reconciliation and the outcome is reported as unprovable. Reuse a stable request ID when retrying, and never retry an ambiguous execution under a new one.

Grant routes

POST /api/grants is the explicit protocol endpoint for clients that need a grant before using a native protocol such as Git. Every request carries a unique client_request_id, reused on retries:

curl -sS -H "Authorization: Bearer $HF_BROKER_SHARED_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "git.push.force",
    "target": {
      "kind": "repo",
      "type": "dataset",
      "owner": "osolmaz",
      "name": "scraped-news",
      "refs": ["refs/heads/main"]
    },
    "reason": "recover main after a bad commit",
    "minutes": 5,
    "max_uses": 1,
    "client_request_id": "recover-main-after-bad-commit"
  }' \
  https://hf-broker.example.com/api/grants

Discrete operations should use the Agent V1 lifecycle instead. Requesting a grant before an ordinary operation creates approval state that nobody needed.

MCP projection

MCP returns a closed unyolo.io/mcp-operation/v1 projection defined in protocol/openapi/mcp-v1.yaml. It excludes clients, canonical arguments, approval linkage, and plan data.

Waits default to 25 seconds and never exceed 25 seconds. Lists default to 20 results, cap at 50, use validated opaque cursors, and support exact request-ID recovery. See MCP servers.

Esc

Type to search across every documentation page.