← Docs · 日本語

AgenTrux Topology Request

The Topology Request flow lets an agent declare the Scripts, Topics, and Grants it needs in a single request. A human reviews that declaration once in the Console and approves it; the agent then receives a Bearer access token that is already scoped to the approved Topics — ready to publish and read.

This is the self-service onboarding path. The agent proposes a topology; a person disposes. The agent can ask to create or attach resources, but only a human, by clicking Approve, actually creates them. Nothing is deleted or downgraded by this flow — removing access is always a Console action.

Which flow do I want?

Flow The Scripts / Topics / Grants are… Who approves Doc
Activation Code already created by the owner; the agent just redeems a code (set up beforehand) API Reference
MCP (interactive OAuth) already exist; the client is granted access to them human, in the browser MCP
Topology Request declared by the agent and created on approval human, in the Console this page

Discovery

The endpoint is advertised in the Authorization Server Metadata, so a client can find it without hard-coding:

curl https://api.agentrux.com/.well-known/oauth-authorization-server
{
  "token_endpoint": "https://api.agentrux.com/oauth/token",
  "topology_request_endpoint": "https://api.agentrux.com/oauth/topology-request",
  "authorization_details_types_supported": ["agentrux.topology"],
  "...": "..."
}
Item Value
Topology Request endpoint https://api.agentrux.com/oauth/topology-request
Token endpoint https://api.agentrux.com/oauth/token (device-code grant)
Client public client registered via Dynamic Client Registration (token_endpoint_auth_method="none")
Authorization details type agentrux.topology (version 1)
Approval window 600 seconds (10 minutes)

Step 1 — Register a public client

Same Dynamic Client Registration used for MCP. Register once and reuse the client_id (dcr_…).

curl -X POST https://api.agentrux.com/oauth/register \
  -H 'Content-Type: application/json' \
  -d '{
    "client_name": "weather-bot",
    "redirect_uris": ["http://127.0.0.1:8765/callback"],
    "token_endpoint_auth_method": "none",
    "grant_types": ["urn:ietf:params:oauth:grant-type:device_code", "refresh_token"]
  }'

The response contains a client_id (prefixed dcr_); reuse it in the next steps. See the MCP doc for the full registration details.

Step 2 — Submit the topology request

POST /oauth/topology-request is form-encoded (application/x-www-form-urlencoded). The authorization_details field carries the declaration as a URL-encoded JSON array with exactly one entry.

Form field Required Description
client_id yes the dcr_… from Step 1
authorization_details yes URL-encoded JSON array (one agentrux.topology entry)
client_hint no ≤256 chars, shown to the human (e.g. app name / version)

The declaration you put in authorization_details:

[
  {
    "type": "agentrux.topology",
    "version": 1,
    "script": {
      "name": "weather-bot",
      "description": "Fetches weather and publishes hourly readings"
    },
    "topics": [
      { "ref": "weather-data", "name": "weather-data", "retention_s": 86400, "intent": "publish hourly readings" }
    ],
    "grants": [
      { "topic_ref": "weather-data", "scope": "write", "binding_name": "weather-out" }
    ]
  }
]

Field rules (your input contract):

Field Rule
type must be "agentrux.topology"
version must be 1
script.name 1–128 chars; lowercase letters, digits, . _ -
script.description 1–256 chars
topics 1–20 entries
topics[].ref 1–128 chars, unique within the request; the connector that ties this topic across request → approval → token
topics[].name 1–128 chars; lowercase letters, digits, . _ -
topics[].retention_s 36002592000 (1 hour – 30 days); the human may shorten it on approval
topics[].intent optional, ≤256 chars; shown to the human
grants 1–40 entries
grants[].topic_ref must match one of topics[].ref
grants[].scope "read" or "write" (one per entry — request both as two entries)
grants[].binding_name optional, 1–64 chars, printable ASCII; a stable label you use to find the grant in the token

The whole declaration must be ≤16 KB. Strings are Unicode-normalized and must not contain control characters.

A complete curl (note --data-urlencode for the JSON field):

curl -X POST https://api.agentrux.com/oauth/topology-request \
  --data-urlencode "client_id=dcr_…" \
  --data-urlencode "client_hint=weather-bot v1.2" \
  --data-urlencode 'authorization_details=[{"type":"agentrux.topology","version":1,"script":{"name":"weather-bot","description":"Fetches weather and publishes hourly readings"},"topics":[{"ref":"weather-data","name":"weather-data","retention_s":86400,"intent":"publish hourly readings"}],"grants":[{"topic_ref":"weather-data","scope":"write","binding_name":"weather-out"}]}]'

Response (200):

{
  "device_code": "dc_…",
  "user_code": "TVHV-QJZW",
  "verification_uri": "https://console.agentrux.com/topology/approve",
  "verification_uri_complete": "https://console.agentrux.com/topology/approve?code=TVHV-QJZW",
  "expires_in": 600,
  "interval": 5
}

Validation errors (400), as OAuth error codes:

error Cause
unsupported_authorization_details_type type is not agentrux.topology
unsupported_authorization_details_version version is not 1
invalid_scope_in_authorization_details a scope is not read / write
invalid_authorization_details schema, naming, size, duplicate, or unknown topic_ref

Submitting too quickly may return 429 too_many_requests.

Step 3 — Send the user to approve

Show the user the user_code and verification_uri, or open verification_uri_complete directly (it pre-fills the code). Use the values the server returned — don't rebuild the URL yourself. In the Console the person:

That click is the authorization boundary. The agent never establishes a topology unattended, and the human can approve only part of what was requested.

Step 4 — Poll for the token

Exchange the device_code at the token endpoint, polling no faster than interval (5 seconds).

curl -X POST https://api.agentrux.com/oauth/token \
  --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
  --data-urlencode "device_code=dc_…" \
  --data-urlencode "client_id=dcr_…"

While the request is still open you get an OAuth error (check error, not the status code alone):

HTTP error Meaning
400 authorization_pending not approved yet — keep polling
400 slow_down polling too fast — increase your interval (429 on IP burst)
400 access_denied the human denied the request — stop
400 expired_token the 10-minute window elapsed — start over
400 invalid_grant the code was already used, or the client_id does not match

On approval (200):

{
  "access_token": "aat_…",
  "token_type": "Bearer",
  "expires_in": 600,
  "refresh_token": "art_…",
  "scope": "topic.write topic:top_<uuid>:write",
  "authorization_details": [
    {
      "type": "agentrux.topology",
      "version": 1,
      "granted": {
        "script_id": "scr_<uuid>",
        "alias_id": "ali_<uuid>",
        "topic_id_map": { "weather-data": "top_<uuid>" },
        "grant_ids": {
          "topic:top_<uuid>:write": { "grant_id": "grt_<uuid>", "binding_name": "weather-out" }
        }
      }
    }
  ]
}

Read authorization_details.granted rather than assuming your request was approved verbatim:

The device-code grant also returns a refresh_token (art_…). When the access token expires (~10 minutes), rotate it with the refresh_token grant (see API Reference). A refresh stays within the scope that was originally approved; to widen access, submit a new topology request (a new human approval).

Step 5 — Publish

The access_token is an ordinary script token. Publish to a granted Topic using the top_<uuid> from topic_id_map:

curl -X POST https://api.agentrux.com/topics/top_<uuid>/events \
  -H "Authorization: Bearer aat_…" \
  -H 'Content-Type: application/json' \
  -d '{ "event_type": "weather.reading", "payload": { "temp_c": 21.4 } }'

The Data Plane (publish / read / stream) is documented in the API Reference; the same token also works over the MCP interface (tools/call publish_event).

What this flow guarantees

Related links