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.
/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.
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.
{
"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.
{
"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.
{
"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.
| Code | Retry behaviour |
|---|---|
TRANSPORT_FAILED | No parseable response arrived. The SDK's one client-side code; the server never returns it. |
RATE_LIMITED | Retried after the server's retry_after_seconds. |
IDEMPOTENCY_IN_PROGRESS | The same request is still being processed; retried with the same key. |