Skip to content

List runs

View as Markdown

This guide lists runs: the newest page by page, only the ones your app started, the runs inside one run, or one agent's turns.

  • Runs to list, on a runtime such as kindgi dev, with Kindgi 0.1's CLI.
  • For the app's half: Node 22.12 or later, Python 3.11 or later, or Java 17 or later, with Kindgi 0.1's client, and KINDGI_API_URL and KINDGI_API_TOKEN set.

The newest runs come first. List two:

Terminal window
pnpm exec kindgi runs list --limit=2

--limit=2 is the most runs on a page. It prints the page:

{
"data": [
{
"id": "657512f8-97b5-41bb-a0cc-396bffe158f6",
…
"flowId": "acme.reserve-order",
"flowVersion": "0.1.0",
"status": "cancelled",
…
},
{
"id": "365d7fd0-7801-43e5-a3c5-66f9479cf02d",
…
}
],
"hasMore": true,
"nextCursor": "eyJjcmVhdGVkQXQiOiIyMDI2LTEwLTAzVDIwOjE0OjE2Ljc0NFoiLCJpZCI6IjM2NWQ3ZmQwLTc4MDEtNDNlNS1hM2M1LTY2Zjk0NzljZjAyZCJ9"
}
Excerpt
  • --limit is 25 by default, and at most 100.
  • --cursor=<nextCursor> gets the next page, where <nextCursor> is the page's nextCursor.
  • The list leaves out each run's output. kindgi runs get <run-id> has it.

The CLI lists every run, including the agent turns inside flows. Each of those is a run of agent.turn, with a parentRunId. --agent=<agent-id> lists one agent's turns, as One agent's turns shows. The clients also filter by status, creation time, flow and version, and scope.

Your app lists runs with runs.list. Ask your coding agent: "I want my app to list the runs it started, newest first, a page at a time." For reference, this code lists the newest runs your app started, then gets the next page:

app/list-runs.ts
import { createClient } from '@kindgi/sdk/client';
const kindgi = createClient(); // KINDGI_API_URL, KINDGI_API_TOKEN
// The newest runs your app started, without the agent turns inside them
const page = await kindgi.runs.list({ topLevel: true, limit: 3 });
for (const run of page.data) console.log(run.id, run.flowId, run.status);
// The next page
if (page.nextCursor !== undefined) {
const next = await kindgi.runs.list({ topLevel: true, limit: 3, cursor: page.nextCursor });
console.log(next.data.length, next.hasMore);
}
f703bffb-367c-4abb-a699-006575b7c21a acme.reserve-order cancelled
54e3258d-3cd3-444a-8175-c965ef6cf682 acme.reserve-order completed
42b7c0c8-3c47-4962-9b08-3319ff887ada acme.review-order completed
3 true

The page holds the runs, and its nextCursor leads to the next one. list takes these filters, with their Python names in brackets:

  • topLevel: true (top_level=True) leaves out runs started inside other runs, such as agent turns: the runs your app and the CLI started.
  • includeOutput: true (include="output") adds each run's output.
  • scope (scope_kind / scope_id) lists one project's runs, or the runs of every project in an org: { kind: 'project', projectId } (scope_kind="project", scope_id=…), or { kind: 'org', orgId }.
  • agentId (agent_id) lists one agent's turns, as One agent's turns shows.
  • status lists the runs in one status, or in any of several: ['failed', 'cancelled'] (a list in Python too).
  • createdAfter / createdBefore (created_after / created_before) list the runs created strictly after, or before, a time.
  • flowId (flow_id) lists one flow's runs, and flowVersion (flow_version) one version's. An agent's turns run the agent.turn flow: use agentId for an agent's.
  • In Python, paginate follows next_cursor for you.

A status that doesn't exist, a time that isn't one, an empty value, or a version without its id is refused with 400 bad-input, naming it:

{ "error": { "code": "bad-input", "message": "`agentVersion` needs `agentId`", … } }
Excerpt

The filters combine. Ask your coding agent, for example: "I want my app to list the runs from the last day that failed or were cancelled." For reference, this code lists them, leaving out the runs inside them:

app/ended-runs.ts
import { createClient } from '@kindgi/sdk/client';
const kindgi = createClient(); // KINDGI_API_URL, KINDGI_API_TOKEN
const since = new Date(Date.now() - 24 * 3_600_000).toISOString();
const ended = await kindgi.runs.list({
status: ['failed', 'cancelled'],
createdAfter: since,
topLevel: true,
});
for (const run of ended.data) console.log(run.id, run.status, run.agent?.version);
c231451d-c304-4466-bb37-3b72145470ed cancelled 2.1.0

A flow's run starts a run for each agent step. parentRunId (parent_run_id) lists the runs a run started, each with the step it belongs to. Ask your coding agent: "I want my app to list the agent turns inside a flow's run." For reference, this code starts a flow's run, then lists the runs inside it:

app/run-children.ts
import { createClient } from '@kindgi/sdk/client';
const kindgi = createClient(); // KINDGI_API_URL, KINDGI_API_TOKEN
const run = await kindgi.runs.start({ flow: 'acme.process-order', input: { orderId: 'A-100' } });
const children = await kindgi.runs.list({ parentRunId: run.id });
for (const child of children.data) console.log(child.id, child.flowId, child.parentNodeId);
eb59636f-aaae-4cd2-84ec-66cbcbf55f83 agent.turn note

An agent's turn names its agent: agent carries the agent's id, the version that ran and the conversation. That goes for an agent run and for the turn a flow's agent step starts. List one agent's turns, at every version:

Terminal window
pnpm exec kindgi runs list --agent=acme.chat-desk --table

--agent is the agent's id, and --table prints a table instead of JSON:

ID STATUS FLOW / AGENT CREATED
──────────────────────────────────── ───────── ──────────────────── ────────────────────────
45d986f1-8a8d-4341-a786-5ddcf239bb93 completed acme.chat-desk@0.1.0 2026-10-11T07:55:48.520Z
95674147-b935-4a63-a74c-cbffc0fb103a completed acme.chat-desk@0.1.0 2026-10-11T07:55:39.011Z

In the clients, it's agentId, or agent_id in Python. Ask your coding agent: "I want my app to list one agent's turns." For reference, the code looks like this:

app/agent-turns.ts
import { createClient } from '@kindgi/sdk/client';
const kindgi = createClient(); // KINDGI_API_URL, KINDGI_API_TOKEN
const turns = await kindgi.runs.list({ agentId: 'acme.desk-agent' });
for (const run of turns.data) {
console.log(run.id, run.agent?.version, run.agent?.conversationId, run.parentRunId ?? '-');
}
51f736ba-bdde-4558-bf5f-32270622b822 1.1.0 d8d51075-ee70-44bd-b93d-f15e450798b7 259f5e11-6ebe-4347-a590-e3db5c71cf7f
f9745c06-9935-4641-bf41-77d11a7f1ffb 1.1.0 b3e40910-9a84-4fc5-a4f8-d2cced5dbb53 -
d0f3817d-1166-462d-a666-7a193bc48f08 1.0.0 60c9d486-ff3b-4ef9-8fbe-be19ab1d7313 -

The first turn is a flow's agent step: it has a parentRunId. Add topLevel: true to leave those out. It combines with scope too. A turn stored by an older runtime may not name its agent. It then has no agent, and agentId doesn't list it.

Add agentVersion (agent_version) for one version's turns, such as to see how a new version is doing. It needs agentId.

To see what a turn did, read its journal.

A project's Runs page lists each agent run or flow run started in the project, newest first, with a flow's agent turns under it. It refreshes every 5 seconds. A flow run's row opens, by its arrow, to its agent turns, each with the step it belongs to. Their cost is in the flow run's. The list has a search box and sorts by a column's header. Columns chooses which columns it shows.

The Runs page with the flow run acme.refunds opened to its agent turns: step answer and step triage, each a Dev-Echo Agent run of demo.echo-agent @1.0.0, under the flow run's $0.08; then a Dev-Echo Agent run of its own, $0.08. A search box and the Columns menu are above the list.

The Runs page filtered to Status: Failed and Started in the last hour: three failed runs of Support agent (two of acme.support @1.1.0, one of @1.0.0), each with when it started, how long it took and its cost.

Its filters:

  • Status: Pending, Running, Waiting, Completed, Failed or Cancelled. A waiting run waits on something, such as an approval.
  • Started: in the last hour, 24 hours, 7 days or 30 days.
  • An agent or a flow, and its version, from a link that names them. A flow's page links Its runs →, and Runs of 1.1.0 → for the version it shows. A schedule's page links Its runs →. Its failed runs on What failed names the agent or flow and its version. With an agent chosen, a Version choice appears: Every version, or one.
  • Include steps inside flows and Include eval replays.

Each filter shows as a chip ("Status: Failed", "Started in the last hour", "Flow: Refunds"). Removing an agent's or a flow's chip removes its version too. The page's address keeps the filters, the sort and the search, so a link opens the same list.

The Runs page reached from a flow's "Runs of 1.1.0 →": the chips Flow: Refunds and Flow version: 1.1.0.

What failed, from the Runs page, groups the project's failed runs by cause and by version, so a bad deploy shows. Approvals people decided are counted apart: they aren't errors.

What failed over the last 7 days: "In the last 7 days, 7 runs failed: 7 errors (in 3 groups)." The errors as bars by version, and a table: an unregistered guardrail (unresolved-guardrail) in Support agent 1.1.0, 4 runs; a guardrail that blocked the answer (guardrail-violation) in Support agent 1.0.0, 2 runs; and a failed run (run-failed) in the flow Refunds 1.0.0, 1 run.

  • The window: the last 24 hours, 7, 30 or 90 days.
  • The headline: "In the last 7 days, 7 runs failed: 7 errors (in 3 groups)."
  • The errors by version: bars of the runs that failed with an error, by agent or flow version, the most first. Show as a table shows the numbers.
  • One row per cause and version: the cause in a run page's words, with its code ("A guardrail blocked the answer." guardrail-violation), what failed at which version, how many runs, when it was first and last seen, The latest run, and Its failed runs on the Runs page.