Agent HTTP API

The HTTP contract behind the projecthubs CLI and the TypeScript Agent SDK. It is in development and versioned. ProjectHubs does not currently offer a separate public REST API or webhooks for customer integrations.

Base path /agent/v1/operations/{operation}

Authentication

Each request carries a bearer credential for an Agent workload identity. Its abilities derive from the Agent's capability grant, which is bound to one project and an expiry and never exceeds its human sponsor's rights. Clients also identify themselves, for example ProjectHubs-Client: projecthubs-cli/0.1.0, so the server can enforce its minimum client version.

Keep credentials out of prompts Agents read the credential from their runtime environment. The CLI never prints it, and its debug output shows Bearer ***. A credential pasted into a prompt ends up in model context and logs.

Versioning and compatibility

The API version is in the path, and every request states its schema_version. Milestones recorded as implemented are listed in the changelog.

Additive changes
New response fields may appear; ignore fields you do not recognise.
Unknown fields
Unknown mutation fields are rejected with SCHEMA_INVALID.
Breaking changes
Need a new schema version and a migration window.
Old clients
A client below the server's minimum version receives CLIENT_UPGRADE_REQUIRED.

Errors

Errors use a standard HTTP status and a stable code, and never leave partial writes. A conflict response includes the safe current version and recovery actions without exposing data the caller may not see. The codes are listed in the Agent protocol reference.

Operations

Each operation is a POST to its own path, for example /agent/v1/operations/work_items.get. The operation catalogue is the whole Agent API: anything not listed does not exist.

work_items.get request
{
  "schema_version": 1,
  "payload": {
    "work_item_public_id": "00000000-0000-0000-0000-000000000000"
  }
}

Mutation envelope

Every mutation carries an idempotency key and, when it revises an existing record, the version it expects. The server authenticates the actor and derives Team, project and capability scope; a caller cannot widen its scope by adding identifiers to the payload.

mutation
{
  "schema_version": 1,
  "idempotency_key": "client-generated-stable-key",
  "expected_version": 12,
  "correlation_id": "workflow-operation-id",
  "payload_hash": "sha256:…",
  "payload": {}
}

Operations inside a run also carry run_id, client_sequence, fencing_token and declaration_hash, and send the lease token in the ProjectHubs-Lease-Token header. The lease token is never written to a receipt, event or log.

Response envelope

A successful response returns the data, the new resource version, and what the caller may do next. Clients use the returned identifiers and versions and never predict the next version or transition.

200 response
{
  "data": {},
  "resource_version": 13,
  "event_id": "event-id",
  "correlation_id": "workflow-operation-id",
  "deduplicated": false,
  "warnings": [],
  "allowed_next_actions": [],
  "blocked_actions": []
}

blocked_actions lists actions the grant holds but the server would refuse now, each with the error code of that refusal. Actions outside the grant appear in neither list.

Retries and idempotency

The same idempotency key with the same body returns the recorded result; reusing a key with a different body is rejected. The SDK retries at most three times with the same key, and only for these codes. It never retries a conflict or a denial.

Codes the SDK retries
CodeRetry behaviour
TRANSPORT_FAILEDNo parseable response arrived. The SDK's one client-side code; the server never returns it.
RATE_LIMITEDRetried after the server's retry_after_seconds.
IDEMPOTENCY_IN_PROGRESSThe same request is still being processed; retried with the same key.

See the Agent protocol reference