Skip to content
Agent Graph

Retrieve an event

GET/graphs/{graph_id}/events/{event_id}

Retrieves one event, with every change it made. expand[]=node adds its node as it stood just after it. An event older than the graph’s retained history is 410 outside_retention_window.

Path ParametersExpand Collapse
graph_id: string
event_id: string
Query ParametersExpand Collapse
expand: optional array of string

Fields to expand: node, and its own fields, node.parent.

Send one expand[] per path. A path goes at most 4 levels deep; at most 20 paths per request. An expanded field appears beside its _id field, which is always there; one not expanded is absent.

ReturnsExpand Collapse
Event object { id, changes, created, 7 more }

One thing that happened in a graph, and every change it made to its nodes.

id: string

Unique identifier for the event, evt_…. Sorts by time.

changes: array of NodeChange { created, fields, node_id }

Every node this event changed, starting with node_id. Empty when it changed nothing (a repeated status, say).

created: boolean

Whether the event created it. Its fields then go from null.

fields: map[FieldChange { from, to } ]

Each node field that changed, by name, from what to what. Derived fields count (child_count, descendant_count, blocked, headline, task_counts). stale doesn’t, as it changes with time rather than events, and nor do expandable fields.

from: unknown

The value before the event.

to: unknown

The value after it.

node_id: string
created: number

When it happened, in Unix milliseconds.

formatint64
graph_id: string
node_id: string

The node it’s about.

object: "event"

String representing the object’s type: always event.

payload: map[unknown]

What the agent tool reported, by type: see event types. Ids in it are the provider’s own. Text in it is untrusted.

source: EventSource { adapter, provider, provider_version }

What reported the event.

adapter: string

The Agent Graph adapter that recorded it, and its version, when it says.

provider: string
provider_version: string

The agent tool’s version, when it says.

type: "session.started" or "session.ended" or "agent.spawned" or 11 more

What happened. See event types. More may be added: ignore those you don’t recognise.

One of the following:
"session.started"
"session.ended"
"agent.spawned"
"agent.finished"
"status"
"tasks.updated"
"task.upserted"
"task.deleted"
"spawn.requested"
"spawn.returned"
"wait.started"
"wait.ended"
"message.sent"
"activity"
node: optional Node { id, agent_type, as_of_event_id, 39 more }

That node, as it stood just after this event. Present only when expanded.

id: string

Unique identifier for the node within its graph: node_ and the base64url of provider_ref.

agent_type: string

For an agent, its type, as the tool names it (Explore, general-purpose, …).

as_of_event_id: string

The event this node is shown as of.

attention: string

While input_required: what the person is being asked. Untrusted text.

background: boolean

Whether it was started in the background, so its requester carries on without waiting. null when unknown.

background_agent_count: number

Helpers its tool ran on its own between turns (memory extraction, summaries, prompt suggestions). They report nothing about what they’re for, so they’re counted, not made nodes.

blocked: Blocked { cycle, node_count, on_ids, 3 more }

What stands between a node and carrying on.

child_count: number

How many nodes sit directly under it.

created: number

When it started (or was first seen), in Unix milliseconds.

formatint64
cwd: string

The directory it runs in, when reported.

depth: number

How far below its root it is: 0 for a root.

minimum0
descendant_count: number

How many nodes sit under it, at any depth: the size of descendants.

ended: number

When it finished, in Unix milliseconds. null while it hasn’t.

formatint64
graph_id: string

The graph it belongs to.

headline: string

One line on what it’s doing now: summary, else the task in progress. Untrusted text.

kind: NodeKind

session: one run of a coding agent (Claude Code, Codex, Cursor, …). agent: an agent started inside a session, by it or by another agent.

One of the following:
"session"
"agent"
last_event: number

When it last had an event, in Unix milliseconds.

formatint64
One of the following:
object: "node"

String representing the object’s type: always node.

parent_id: string

The node it sits under: the agent or session that started it. null for a root.

provider: string

The agent tool: claude-code, codex, cursor, or another that reports to Agent Graph.

provider_ref: string

The id the agent tool gave it: <provider>:<session> for a session, <provider>:<session>/<agent> for an agent. Not an id in this API: use it to match the node to the tool’s own records.

purpose: string

Why it was started, from the request that started it. Untrusted text.

requested_by_id: string

The node whose spawn request started it, when known. Usually the parent; null for a session nothing started, or an agent no request was matched to.

root_id: string

The top of its tree: follow parent_id until it’s null. A session started by another session is in that session’s tree. A root’s root_id is its own id.

session_id: string

The session it runs in: itself, for a session; for an agent, the nearest session above it.

spawn_call_id: string

The tool call, in its requester’s session, that started it: matches a spawns[].call_id on requested_by.

stale: boolean

working, waiting on nothing, and silent for 30 minutes: it may have hung or crashed. Measured against as_of, not now.

state: NodeState

What a node is doing.

  • working: doing something.
  • input_required: waiting on a person (attention says what for).
  • idle: a session between turns, waiting for its next prompt.
  • completed, failed, canceled: finished.
One of the following:
"working"
"input_required"
"idle"
"completed"
"failed"
"canceled"
summary: string

Its own latest status line, if it reports one. Untrusted text.

task_counts: TaskCounts { completed, in_progress, open, 2 more }

Its tasks, by status.

completed: number
in_progress: number
open: number

Not completed: pending and in_progress.

pending: number
total: number
title: string

The session’s name, as its tool shows it. It can change. Untrusted text.

children: optional unknown

The nodes directly under it, oldest first: the first 100, and a url for the rest. Present only when expanded.

descendants: optional unknown

Every node under it, at any depth, as one flat list in tree order: each parent before its children, siblings oldest first. The first 1,000, and a url for the rest. Present only when expanded.

messages: optional array of Message { id, body, created, 5 more }

Messages it has sent and received, oldest first. Present only when expanded.

id: string

The tool’s id for the message.

body: string

The whole message, only if the share was made with body capture on. Untrusted text.

created: number

When it was sent, in Unix milliseconds.

formatint64
direction: "sent" or "received"
One of the following:
"sent"
"received"
peer_id: string

The node on the other side, when it’s one in this graph.

peer_name: string

The tool’s name for the other side, when it isn’t a node in this graph.

reply_to_message_id: string

The message it answers.

summary: string

Untrusted text.

parent: optional Node { id, agent_type, as_of_event_id, 39 more }

The parent node. Present only when expanded.

requested_by: optional Node { id, agent_type, as_of_event_id, 39 more }

The node that requested it. Present only when expanded.

root: optional Node { id, agent_type, as_of_event_id, 39 more }

The root node. Present only when expanded.

session: optional Node { id, agent_type, as_of_event_id, 39 more }

The session node. Present only when expanded.

spawns: optional array of Spawn { agent_type, background, call_id, 7 more }

The children it has asked for, oldest first. Present only when expanded.

agent_type: string
background: boolean

If false, the requester is blocked until the call returns.

call_id: string

The tool call that asked for it.

child_id: string

The node it started, once matched. Before the call returns this can be a best guess, corrected when it does.

kind: "agent" or "session"

agent: an agent in the same session. session: a separate session, e.g. codex exec run from a shell.

One of the following:
"agent"
"session"
purpose: string

Untrusted text.

requested: number

When it was asked for, in Unix milliseconds.

formatint64
returned: boolean

Whether the call has returned.

run: boolean

Whether it’s through agent-graph run, when known.

title: string

For a session, the name it was to be given.

tasks: optional array of Task { id, active_text, status, text }

Its task list, in the tool’s order. Present only when expanded.

id: string

The tool’s id for the task, unique within the node.

active_text: string

How the tool words it while it’s in progress (Running the tests). Untrusted text.

status: "pending" or "in_progress" or "completed"
One of the following:
"pending"
"in_progress"
"completed"
text: string

What the task is. Untrusted text.

waits: optional array of Wait { id, ended, kind, 4 more }

What it has waited on and is waiting on, oldest first. Present only when expanded.

id: string

The wait’s id, unique within the node.

ended: number

When it stopped, in Unix milliseconds.

formatint64
kind: "spawn" or "explicit"

spawn: waiting for a child it asked for, until the call returns. explicit: any other wait the tool reported.

One of the following:
"spawn"
"explicit"
on_id: string

The node waited on. null while a requested child hasn’t started.

open: boolean

Whether it’s still waiting.

reason: string

Untrusted text.

started: number

When it started waiting, in Unix milliseconds.

formatint64

Retrieve an event

curl https://agentgraph.chofter.com/api/v1/graphs/$GRAPH_ID/events/$EVENT_ID \
    -H "Authorization: Bearer $AGENT_GRAPH_API_KEY"
{
  "id": "evt_01M4G2FMPN7KD3N1PZ0QX8RM4A",
  "object": "event",
  "type": "agent.spawned",
  "created": 1791540843221,
  "graph_id": "gph_k3P9xQ2mWt7a",
  "node_id": "node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEwL2EzZmQwN2MyYjE5ZTRkNjE",
  "source": {
    "provider": "claude-code",
    "provider_version": "2.1.260",
    "adapter": "claude-code@1"
  },
  "payload": {
    "agent_type": "Explore",
    "purpose": "Find every caller of the old session store"
  },
  "changes": [
    {
      "node_id": "node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEwL2EzZmQwN2MyYjE5ZTRkNjE",
      "created": true,
      "fields": {
        "state": {
          "from": null,
          "to": "working"
        },
        "parent_id": {
          "from": null,
          "to": "node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEw"
        }
      }
    },
    {
      "node_id": "node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEw",
      "created": false,
      "fields": {
        "child_count": {
          "from": 2,
          "to": 3
        },
        "descendant_count": {
          "from": 4,
          "to": 5
        },
        "blocked": {
          "from": null,
          "to": {
            "on_ids": [
              "node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEwL2EzZmQwN2MyYjE5ZTRkNjE"
            ],
            "starting": 0,
            "node_count": 1,
            "open_tasks": 0,
            "cycle": false
          }
        }
      }
    }
  ]
}
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid",
    "message": "Invalid limit: must be between 1 and 1000.",
    "param": "limit",
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}
{
  "error": {
    "type": "invalid_request_error",
    "code": "expand_too_deep",
    "message": "The path children.children.children.children.children goes 5 levels deep; at most 4 are allowed.",
    "param": "expand",
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}
{
  "error": {
    "type": "authentication_error",
    "code": "api_key_invalid",
    "message": "Invalid API key: ag_sk_live_****Xa9T.",
    "param": null,
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}
{
  "error": {
    "type": "permission_error",
    "code": "api_key_restricted",
    "message": "This restricted key can't read gph_k3P9xQ2mWt7a.",
    "param": null,
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}
{
  "error": {
    "type": "invalid_request_error",
    "code": "resource_missing",
    "message": "No such node: node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEwL2I4MWMyMmUwOWY3YTNjNTU.",
    "param": "node_id",
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}
{
  "error": {
    "type": "invalid_request_error",
    "code": "node_not_yet_created",
    "message": "The node node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEwL2EzZmQwN2MyYjE5ZTRkNjE is created by evt_01M4G2FMPN7KD3N1PZ0QX8RM4A, after as_of.",
    "param": "as_of",
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors",
    "first_event_id": "evt_01M4G2FMPN7KD3N1PZ0QX8RM4A"
  }
}
{
  "error": {
    "type": "invalid_request_error",
    "code": "outside_retention_window",
    "message": "This graph holds events from evt_01M4FXYWR82B8XK0V5QJ7M1N3R to evt_01M4G3G4E8Q9R2M5X4T6W8Y0B1.",
    "param": "as_of",
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors",
    "first_event_id": "evt_01M4FXYWR82B8XK0V5QJ7M1N3R",
    "last_event_id": "evt_01M4G3G4E8Q9R2M5X4T6W8Y0B1"
  }
}
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit",
    "message": "Too many requests. Try again in 1 second.",
    "param": null,
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}
{
  "error": {
    "type": "api_error",
    "code": "api_error",
    "message": "Something went wrong. Try again, and include the Request-Id if it keeps happening.",
    "param": null,
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}
Returns Examples
{
  "id": "evt_01M4G2FMPN7KD3N1PZ0QX8RM4A",
  "object": "event",
  "type": "agent.spawned",
  "created": 1791540843221,
  "graph_id": "gph_k3P9xQ2mWt7a",
  "node_id": "node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEwL2EzZmQwN2MyYjE5ZTRkNjE",
  "source": {
    "provider": "claude-code",
    "provider_version": "2.1.260",
    "adapter": "claude-code@1"
  },
  "payload": {
    "agent_type": "Explore",
    "purpose": "Find every caller of the old session store"
  },
  "changes": [
    {
      "node_id": "node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEwL2EzZmQwN2MyYjE5ZTRkNjE",
      "created": true,
      "fields": {
        "state": {
          "from": null,
          "to": "working"
        },
        "parent_id": {
          "from": null,
          "to": "node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEw"
        }
      }
    },
    {
      "node_id": "node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEw",
      "created": false,
      "fields": {
        "child_count": {
          "from": 2,
          "to": 3
        },
        "descendant_count": {
          "from": 4,
          "to": 5
        },
        "blocked": {
          "from": null,
          "to": {
            "on_ids": [
              "node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEwL2EzZmQwN2MyYjE5ZTRkNjE"
            ],
            "starting": 0,
            "node_count": 1,
            "open_tasks": 0,
            "cycle": false
          }
        }
      }
    }
  ]
}
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid",
    "message": "Invalid limit: must be between 1 and 1000.",
    "param": "limit",
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}
{
  "error": {
    "type": "invalid_request_error",
    "code": "expand_too_deep",
    "message": "The path children.children.children.children.children goes 5 levels deep; at most 4 are allowed.",
    "param": "expand",
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}
{
  "error": {
    "type": "authentication_error",
    "code": "api_key_invalid",
    "message": "Invalid API key: ag_sk_live_****Xa9T.",
    "param": null,
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}
{
  "error": {
    "type": "permission_error",
    "code": "api_key_restricted",
    "message": "This restricted key can't read gph_k3P9xQ2mWt7a.",
    "param": null,
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}
{
  "error": {
    "type": "invalid_request_error",
    "code": "resource_missing",
    "message": "No such node: node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEwL2I4MWMyMmUwOWY3YTNjNTU.",
    "param": "node_id",
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}
{
  "error": {
    "type": "invalid_request_error",
    "code": "node_not_yet_created",
    "message": "The node node_Y2xhdWRlLWNvZGU6NWYyYzFlOWEtOGQxYi00YjZlLTlhNTEtMGY2ZjJjN2QzZTEwL2EzZmQwN2MyYjE5ZTRkNjE is created by evt_01M4G2FMPN7KD3N1PZ0QX8RM4A, after as_of.",
    "param": "as_of",
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors",
    "first_event_id": "evt_01M4G2FMPN7KD3N1PZ0QX8RM4A"
  }
}
{
  "error": {
    "type": "invalid_request_error",
    "code": "outside_retention_window",
    "message": "This graph holds events from evt_01M4FXYWR82B8XK0V5QJ7M1N3R to evt_01M4G3G4E8Q9R2M5X4T6W8Y0B1.",
    "param": "as_of",
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors",
    "first_event_id": "evt_01M4FXYWR82B8XK0V5QJ7M1N3R",
    "last_event_id": "evt_01M4G3G4E8Q9R2M5X4T6W8Y0B1"
  }
}
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit",
    "message": "Too many requests. Try again in 1 second.",
    "param": null,
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}
{
  "error": {
    "type": "api_error",
    "code": "api_error",
    "message": "Something went wrong. Try again, and include the Request-Id if it keeps happening.",
    "param": null,
    "doc_url": "https://agentgraph.chofter.com/docs/reference#errors"
  }
}