Agent

For instructions on how to authenticate to use this endpoint, see API overview.

Endpoints

POST
POST
GET
PATCH
DELETE
GET
GET
POST
POST
GET
GET
POST
GET
POST
POST
GET
GET
GET
GET

Create agent applications revisions validate

Pre-flight checks before freeze + promote: agent.md exists, every native tool id is registered, every custom tool has its compiled.js + schema.json, every skill path exists, every declared secret has a value set in this revision's env block. Returns { ok, errors: [...] }. Works on any revision state.

Required API key scopes

agents:read

Path parameters

  • application_id
    string
  • id
    string

Response


Example request

POST /api/projects/:project_id/agent_applications/:application_id/revisions/:id/validate
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:application_id/revisions/:id/validate/

Example response

Status 200
RESPONSE
{
"ok": true,
"revision_id": "f8f7f022-982b-4bef-ba7d-4bb808fdbe2a",
"revision_state": "string",
"errors": [
{
"code": "string",
"message": "string",
"pointer": "string"
}
],
"resolved_natives": [
"string"
]
}

Create agent applications revisions new draft

Create a fresh draft revision under application_id and seed it from source_revision_id. Saves the MCP one round-trip vs the explicit create + clone_from sequence.

Required API key scopes

agents:write

Path parameters

  • application_id
    string

Request parameters

  • application_id
    string
  • source_revision_id
    string

Response


Example request

POST /api/projects/:project_id/agent_applications/:application_id/revisions/new_draft
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:application_id/revisions/new_draft/\
-d application_id="string",\
-d source_revision_id="string"

Example response

Status 200
RESPONSE
{
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"application": "2b22d485-f04e-492b-b364-e14f8506726a",
"parent_revision": "7dd0ec7f-ff92-4923-86ab-83534b1f3236",
"state": "draft",
"bundle_uri": "",
"bundle_sha256": "string",
"spec": null,
"skill_refs": [
{
"from_template": "string",
"alias": "string",
"version": 1
}
],
"created_by_id": 0,
"created_by": {
"id": 0,
"first_name": "string",
"email": "user@example.com"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z"
}

Retrieve agent applications

Agent applications — the deployable unit of the platform.

URLs: GET /api/projects/<team>/agent_applications/ list POST /api/projects/<team>/agent_applications/ create GET /api/projects/<team>/agent_applications/<id|slug>/ retrieve PATCH /api/projects/<team>/agent_applications/<id|slug>/ update DELETE /api/projects/<team>/agent_applications/<id|slug>/ archive POST /api/projects/<team>/agent_applications/<id|slug>/set_env/ bulk replace env GET /api/projects/<team>/agent_applications/<id|slug>/env_keys/ list set keys GET /api/projects/<team>/agent_applications/<id|slug>/env_keys/<KEY>/ is one key set? PUT /api/projects/<team>/agent_applications/<id|slug>/env_keys/<KEY>/ set one key DELETE /api/projects/<team>/agent_applications/<id|slug>/env_keys/<KEY>/ clear one key

Required API key scopes

agents:read

Path parameters

  • id
    string

Response


Example request

GET /api/projects/:project_id/agent_applications/:id
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/

Example response

Status 200
RESPONSE
{
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"team_id": 0,
"name": "string",
"slug": "string",
"description": "string",
"live_revision": "067b8498-180d-45ba-92a8-76a49fa0e492",
"archived": true,
"archived_at": "2019-08-24T14:15:22Z",
"created_by_id": 0,
"created_by": {
"id": 0,
"first_name": "string",
"email": "user@example.com"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"slack_events_url": "http://example.com",
"slack_interactivity_url": "http://example.com",
"ingress_base_url": "http://example.com"
}

Update agent applications

Agent applications — the deployable unit of the platform.

URLs: GET /api/projects/<team>/agent_applications/ list POST /api/projects/<team>/agent_applications/ create GET /api/projects/<team>/agent_applications/<id|slug>/ retrieve PATCH /api/projects/<team>/agent_applications/<id|slug>/ update DELETE /api/projects/<team>/agent_applications/<id|slug>/ archive POST /api/projects/<team>/agent_applications/<id|slug>/set_env/ bulk replace env GET /api/projects/<team>/agent_applications/<id|slug>/env_keys/ list set keys GET /api/projects/<team>/agent_applications/<id|slug>/env_keys/<KEY>/ is one key set? PUT /api/projects/<team>/agent_applications/<id|slug>/env_keys/<KEY>/ set one key DELETE /api/projects/<team>/agent_applications/<id|slug>/env_keys/<KEY>/ clear one key

Required API key scopes

agents:write

Path parameters

  • id
    string

Request parameters

  • name
    string
  • slug
    string
  • description
    string
  • archived
    boolean

Response


Example request

PATCH /api/projects/:project_id/agent_applications/:id
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl -X PATCH \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/\
-d team_id="integer"

Example response

Status 200
RESPONSE
{
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"team_id": 0,
"name": "string",
"slug": "string",
"description": "string",
"live_revision": "067b8498-180d-45ba-92a8-76a49fa0e492",
"archived": true,
"archived_at": "2019-08-24T14:15:22Z",
"created_by_id": 0,
"created_by": {
"id": 0,
"first_name": "string",
"email": "user@example.com"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"slack_events_url": "http://example.com",
"slack_interactivity_url": "http://example.com",
"ingress_base_url": "http://example.com"
}

Delete agent applications

Agent applications — the deployable unit of the platform.

URLs: GET /api/projects/<team>/agent_applications/ list POST /api/projects/<team>/agent_applications/ create GET /api/projects/<team>/agent_applications/<id|slug>/ retrieve PATCH /api/projects/<team>/agent_applications/<id|slug>/ update DELETE /api/projects/<team>/agent_applications/<id|slug>/ archive POST /api/projects/<team>/agent_applications/<id|slug>/set_env/ bulk replace env GET /api/projects/<team>/agent_applications/<id|slug>/env_keys/ list set keys GET /api/projects/<team>/agent_applications/<id|slug>/env_keys/<KEY>/ is one key set? PUT /api/projects/<team>/agent_applications/<id|slug>/env_keys/<KEY>/ set one key DELETE /api/projects/<team>/agent_applications/<id|slug>/env_keys/<KEY>/ clear one key

Required API key scopes

agents:write

Path parameters

  • id
    string

Example request

DELETE /api/projects/:project_id/agent_applications/:id
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl -X DELETE \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/

Example response

Status 204 No response body

List all agent applications approvals

List approval-gated tool requests for this application. Team-admin only (per plan §6.1). Default returns all states — pass ?state=queued for the inbox view.

Required API key scopes

agents:read

Path parameters

  • id
    string

Query parameters

  • limit
    integer
  • offset
    integer
  • state
    string

Response


Example request

GET /api/projects/:project_id/agent_applications/:id/approvals
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/approvals/

Example response

Status 200
RESPONSE
{
"results": [
{
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
"application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c",
"team_id": 0,
"revision_id": "f8f7f022-982b-4bef-ba7d-4bb808fdbe2a",
"turn": 0,
"tool_call_id": "string",
"tool_name": "string",
"proposed_args": {},
"decided_args": {},
"assistant_message": {},
"approver_scope": {},
"state": "queued",
"decision_by": "string",
"decision_at": "2019-08-24T14:15:22Z",
"decision_reason": "string",
"dispatch_outcome": {},
"created_at": "2019-08-24T14:15:22Z",
"expires_at": "2019-08-24T14:15:22Z"
}
]
}

Retrieve agent applications approvals

Single approval request — full proposed args, assistant snapshot, decision metadata, dispatch outcome. Team-admin only (plan §6.1).

Required API key scopes

agents:read

Path parameters

  • approval_id
    string
  • id
    string

Example request

GET /api/projects/:project_id/agent_applications/:id/approvals/:approval_id
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/approvals/:approval_id/

Example response

Status 200 No response body

Create agent applications approvals

Approve or reject a queued agent-type tool-approval request.

This is the OWNER decision surface — the only PostHog-authoritative one: team admins decide here, in the console. principal-type approvals are decided by the session principal at the ingress decision API, not here. The runtime side runs the tool platform-side on approve and wakes the session with a synthetic tool_result either way.

Required API key scopes

agents:write

Path parameters

  • approval_id
    string
  • id
    string

Request parameters

  • decision
  • edited_args
    object
  • reason
    string

Response


Example request

POST /api/projects/:project_id/agent_applications/:id/approvals/:approval_id/decide
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/approvals/:approval_id/decide/\
-d decision=undefined

Example response

Status 200
RESPONSE
{
"ok": true,
"state": "string"
}

Create agent applications

Start a new session on this agent's LIVE (promoted) revision.

Bridges to ingress POST /agents/<slug>/run, forwarding the caller's PAT so the session principal is the real caller. Returns the new session_id; drive the conversation with agent-applications-send and read progress with agent-applications-listen. For non-live / draft revisions use preview_proxy instead.

Required API key scopes

agents:write

Path parameters

  • id
    string

Request parameters

  • message
    string
  • external_key
    string

Response


Example request

POST /api/projects/:project_id/agent_applications/:id/invoke
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/invoke/\
-d message="string"

Example response

Status 200
RESPONSE
{
"session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
"state": "queued",
"resumed": true
}

List all agent applications

Poll a LIVE session's progress as a single JSON digest (non-streaming, MCP-friendly). Bridges to the internal ingress digest RPC — the digest is built node-side (never in Python). Tenancy is enforced by the team-scoped get_object() here plus the ingress digest's application_id re-scope; there is no janitor pre-check on this polled path (see the comment below).

Required API key scopes

agents:read

Path parameters

  • id
    string

Query parameters

  • cursor
    integer
  • max_chars
    integer
  • session_id
    string

Response


Example request

GET /api/projects/:project_id/agent_applications/:id/listen
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/listen/

Example response

Status 200
RESPONSE
{
"session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
"state": "queued",
"turns": 0,
"next_cursor": 0,
"digest": "string",
"truncated": true,
"done": true
}

Retrieve agent applications preview proxy

GET passthrough for the preview-proxy — used for /listen SSE.

Required API key scopes

agents:read

Path parameters

  • id
    string
  • rest
    string

Query parameters

  • format
    string
    One of: "json""sse"
  • revision_id
    string

Response


Example request

GET /api/projects/:project_id/agent_applications/:id/preview-proxy/:rest
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/preview-proxy/:rest/

Example response

Status 200
RESPONSE
{
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"team_id": 0,
"name": "string",
"slug": "string",
"description": "string",
"live_revision": "067b8498-180d-45ba-92a8-76a49fa0e492",
"archived": true,
"archived_at": "2019-08-24T14:15:22Z",
"created_by_id": 0,
"created_by": {
"id": 0,
"first_name": "string",
"email": "user@example.com"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"slack_events_url": "http://example.com",
"slack_interactivity_url": "http://example.com",
"ingress_base_url": "http://example.com"
}

Create agent applications preview

Authoring-side proxy for invoking a draft (or any non-live) revision.

Closes the anonymous-draft-invoke gap: the public ingress URL refuses non-live invokes that don't carry the x-agent-preview-secret header; this proxy attaches it after authenticating the Django caller.

URL: /api/projects/<team>/agent_applications/<app>/preview-proxy/<rest> Auth: standard PAT / session — agents:write scope (POST run/send/cancel is a mutating invoke; the read-only listen GET is agents:read).

Required API key scopes

agents:write

Path parameters

  • id
    string
  • rest
    string

Query parameters

  • format
    string
    One of: "json""sse"
  • revision_id
    string

Request parameters

  • message
    string
  • session_id
    string

Example request

POST /api/projects/:project_id/agent_applications/:id/preview-proxy/:rest
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/preview-proxy/:rest/\
-d message="string"

Example response

Status 200

Retrieve agent applications preview

GET sibling of preview_token_mint. Same body and response shape — exists because EventSource can't set headers, so SSE callers fetch the token via GET and then attach ?preview_token= to the ingress URL. Behind the same URL (url_path="preview-token") thanks to DRF's @<action>.mapping.get; DRF resolves it to a distinct view.action, but it is in scope_object_write_actions alongside the POST sibling — both return a usable credential, so both require agents:write.

Required API key scopes

agents:write

Path parameters

  • id
    string

Query parameters

  • revision_id
    string

Response


Example request

GET /api/projects/:project_id/agent_applications/:id/preview-token
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/preview-token/

Example response

Status 200
RESPONSE
{
"token": "string",
"expires_in": 0,
"ingress_slug": "string",
"endpoints": null,
"auth": null,
"preview_proxy": null
}

Create agent applications preview token

Mint a short-lived JWT for talking to a non-live revision directly via the public ingress URL. The caller attaches it as the x-agent-preview-token header (or ?preview_token= query param for EventSource). See _mint_preview_jwt for the payload + claim binding.

The response also includes endpoints, auth, and preview_proxy blocks so the caller can wire a preview invocation without grepping the agent-ingress source for which path each trigger exposes or which header name carries the token. This is the "self-describing" half of preview-mode — every piece of info you need to hit ingress is in one response.

POST is the canonical verb — minting credentials for downstream run/send/cancel is a write-class capability. A GET sibling exists at the same URL for EventSource callers (which can't set headers); it is also write-scoped, since it returns the same token.

Required API key scopes

agents:write

Path parameters

  • id
    string

Query parameters

  • revision_id
    string

Response


Example request

POST /api/projects/:project_id/agent_applications/:id/preview-token
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/preview-token/

Example response

Status 200
RESPONSE
{
"token": "string",
"expires_in": 0,
"ingress_slug": "string",
"endpoints": null,
"auth": null,
"preview_proxy": null
}

Create agent applications

Append a message to an existing LIVE session and re-queue it.

Bridges to ingress POST /agents/<slug>/send, forwarding the caller's PAT so the ACL principal-match passes. A completed session is NOT terminal — it's a per-turn idle state for a multi-turn agent, so send re-queues it for another turn; only truly-terminal states (failed / cancelled / closed) 410, which passes through as a 410. A janitor ownership pre-check runs first, but it's redundant defense-in-depth (ingress /send already app-scopes the load), kept for a clean early 404.

Required API key scopes

agents:write

Path parameters

  • id
    string

Request parameters

  • session_id
    string
  • message
    string

Response


Example request

POST /api/projects/:project_id/agent_applications/:id/send
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/send/\
-d session_id="string",\
-d message="string"

Example response

Status 200
RESPONSE
{
"state": "queued"
}

List all agent applications sessions

List sessions for this application, most recently active first. Strips the conversation transcript from each summary, but includes a preview (last assistant text, ~120 chars) and usage_total (token + cost aggregate). Use agent-applications-sessions-retrieve for the full transcript of a single session.

Required API key scopes

agents:read

Path parameters

  • id
    string

Query parameters

  • created_after
    string
  • created_before
    string
  • limit
    integer
  • offset
    integer
  • revision_id
    string
  • state
    string

Response


Example request

GET /api/projects/:project_id/agent_applications/:id/sessions
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/sessions/

Example response

Status 200
RESPONSE
{
"results": [
{
"usage_total": {
"tokens_in": 0,
"tokens_out": 0,
"cache_read": 0,
"cache_write": 0,
"cost_input": 0.1,
"cost_output": 0.1,
"cost_cache_read": 0.1,
"cost_cache_write": 0.1,
"cost_total": 0.1
},
"principal": {
"kind": "anonymous",
"id": "string",
"team_id": 0
},
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c",
"revision_id": "f8f7f022-982b-4bef-ba7d-4bb808fdbe2a",
"state": "queued",
"external_key": "string",
"trigger_metadata": {},
"turns": 0,
"preview": "string",
"retry_count": 0,
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z"
}
],
"count": 0
}

Retrieve agent applications sessions

Fetch one session's state — full conversation by default, or just the trailing N messages with ?last_n=. Always returns a usage_total block aggregated over the entire session, regardless of trim. The runner-side queue DB is the source of truth.

Required API key scopes

agents:read

Path parameters

  • id
    string
  • session_id
    string

Query parameters

  • last_n
    integer

Response


Example request

GET /api/projects/:project_id/agent_applications/:id/sessions/:session_id
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/sessions/:session_id/

Example response

Status 200
RESPONSE
{
"usage_total": {
"tokens_in": 0,
"tokens_out": 0,
"cache_read": 0,
"cache_write": 0,
"cost_input": 0.1,
"cost_output": 0.1,
"cost_cache_read": 0.1,
"cost_cache_write": 0.1,
"cost_total": 0.1
},
"principal": {
"kind": "anonymous",
"id": "string",
"team_id": 0
},
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"application_id": "48ac72d0-a829-4896-a067-dcb1c2b0f30c",
"revision_id": "f8f7f022-982b-4bef-ba7d-4bb808fdbe2a",
"team_id": 0,
"external_key": "string",
"trigger_metadata": {},
"state": "queued",
"conversation": [
{
"role": "user",
"content": null,
"timestamp": 0
}
],
"pending_inputs": [
{
"role": "user",
"content": null,
"timestamp": 0
}
],
"retry_count": 0,
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"conversation_trimmed": true,
"conversation_total_turns": 0
}

Retrieve agent applications session

Read the runner's structured event log for one session from ClickHouse. Filters (limit / after / before / level / search) match the shared LogEntryMixin helper used by hog_function + hog_flow.

Required API key scopes

agents:read

Path parameters

  • id
    string
  • session_id
    string

Query parameters

  • after
    string
  • before
    string
  • instance_id
    string
  • level
    string
  • limit
    integer
    Default: 50
  • search
    string

Response


Example request

GET /api/projects/:project_id/agent_applications/:id/sessions/:session_id/logs
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/sessions/:session_id/logs/

Example response

Status 200
RESPONSE
{
"results": [
{
"log_source_id": "string",
"instance_id": "string",
"timestamp": "2019-08-24T14:15:22Z",
"level": "string",
"message": "string"
}
]
}

Retrieve agent applications

Roll-up stats for the agent — drives the agent-detail overview tiles.

Required API key scopes

agents:read

Path parameters

  • id
    string

Query parameters

  • since
    string

Response


Example request

GET /api/projects/:project_id/agent_applications/:id/stats
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/agent_applications/:id/stats/

Example response

Status 200
RESPONSE
{
"liveCount": 0,
"sessionsInWindowCount": 0,
"spendInWindowUsd": 0.1,
"lastActivityAt": "2019-08-24T14:15:22Z",
"failedInWindowCount": 0,
"pendingApprovalsCount": 0
}

Community questions