Executions

Follow one agent run from request to result, including status, input, output, latency, cost, and trace links.

An execution is one run of an agent. It starts when your app, webhook, schedule, chat session, or Studio action invokes the agent and ends when the run completes, fails, is cancelled, or waits for approval.

Use executions as the run ledger for the workspace. When someone asks "what happened to that agent request?", the execution record gives you the status, input, output, duration, cost, and trace link.

Execution history is visible from the traces area. Use the filters to narrow by kind, status, level, source, or tag, then open a run for the full span tree.

What Executions Answer

Executions are useful before you open the deeper trace view:

  • Did it finish? Check whether the run completed, failed, was cancelled, or is waiting for approval.
  • What did it receive and return? Review the request input and final output.
  • How expensive was it? See token usage, estimated cost, and duration for the full run.
  • Where do I debug it? Open the linked trace to inspect prompts, model calls, tools, guardrails, and errors.

Execution Lifecycle

At a high level, an execution moves through these states:

  1. Pending -- The execution is created and queued
  2. Running -- The execution pipeline is actively processing (prompt rendering, LLM calls, tool invocations, guardrail checks)
  3. Terminal or paused state -- The execution reaches completed, failed, cancelled, awaiting_approval, or rejected
1Pending
2Running
3Completed, Failed, Cancelled, or Awaiting Approval

Use the terminal states to decide the next action: open the trace for failures, approve or reject paused runs, compare repeated runs when quality changes, and review cost when a workflow becomes expensive.

Technical detailsExecution data model

Status Types

StatusDescription
pendingExecution created, waiting to be processed
runningActively executing (LLM calls, tools, etc.)
completedSuccessfully finished with output
failedEncountered an error during execution
cancelledManually cancelled before completion
awaiting_approvalPaused at a checkpoint, waiting for human approval
rejectedHuman reviewer rejected the execution at an approval checkpoint

Input and Output

Input

The input is the JSON object passed by the caller. If the active agent version has an input schema, PromptRails validates the request before the run starts.

{
  "message": "What is the status of order #12345?",
  "customer_id": "cust_789",
  "language": "en"
}

Output

The output is the result produced by the agent. Its shape depends on the agent type and any output schema configured on the active version.

{
  "response": "Your order #12345 is currently in transit and expected to arrive by Friday.",
  "confidence": 0.95,
  "sources": ["order_database"]
}

Token Usage and Cost

Every execution tracks token consumption and estimated cost:

FieldDescription
token_usageJSON object with prompt and completion token counts
costTotal cost in USD (calculated from token usage and model pricing)
duration_msTotal execution time in milliseconds

Token usage example:

{
  "prompt_tokens": 450,
  "completion_tokens": 120,
  "total_tokens": 570
}

Metadata

Executions can carry arbitrary metadata for tracking and filtering:

result = client.agents.execute(
    agent_id="your-agent-id",
    input={"message": "Hello"},
    metadata={
        "user_id": "user-456",
        "channel": "web",
        "environment": "production",
        "experiment_id": "exp-001"
    }
)
Technical detailsExecution API examples and fields

Sync vs Async Execution

Synchronous Execution

The default execution mode. The API call blocks until the execution completes and returns the result.

result = client.agents.execute(
    agent_id="your-agent-id",
    input={"message": "Hello"}
)
# Result is immediately available
print(result["data"]["output"])

Asynchronous Execution

For long-running executions, use async mode. The API returns immediately with the execution ID, and you poll for completion.

# Start async execution
execution = client.agents.execute(
    agent_id="your-agent-id",
    input={"message": "Analyze this large dataset..."},
    async_mode=True
)
 
execution_id = execution["data"]["id"]
 
# Poll for completion
import time
while True:
    status = client.executions.get(execution_id=execution_id)
    if status["data"]["status"] in ["completed", "failed", "rejected"]:
        break
    time.sleep(1)
 
print(status["data"]["output"])

Streaming Execution Events

Instead of polling, subscribe to the execution's Server-Sent Events stream to receive thinking, tool_start, tool_end, content, and done frames as they happen.

GET /api/v1/executions/{execution_id}/stream
Accept: text/event-stream

The event schema is identical to the chat streaming endpoint — see Sessions and Chat for the full table. Useful when the execution was started outside a chat session (e.g. a one-shot agents.execute or a webhook trigger) and you still want live updates.

// JavaScript / TypeScript
for await (const event of client.executions.stream(executionId)) {
  if (event.type === 'content') process.stdout.write(event.content)
  if (event.type === 'done') break
}
# Python — sync iterator (AsyncExecutionsResource.stream for async)
from promptrails import ContentEvent, DoneEvent
 
for event in client.executions.stream(execution_id):
    if isinstance(event, ContentEvent):
        print(event.content, end="", flush=True)
    elif isinstance(event, DoneEvent):
        break
// Go
stream, _ := client.Executions.Stream(ctx, executionID)
defer stream.Close()
for stream.Next() {
    if e, ok := stream.Event().(*promptrails.ContentEvent); ok {
        fmt.Print(e.Content)
    }
}

Already-completed executions emit a single done (or error) frame and close, so the same code works whether you subscribe mid-run or after the fact.

Listing and Filtering Executions

# List all executions
executions = client.executions.list(page=1, limit=20)
 
# Filter by agent
executions = client.executions.list(
    agent_id="your-agent-id",
    page=1,
    limit=20
)
 
# Filter by status
executions = client.executions.list(
    status="completed",
    page=1,
    limit=20
)

JavaScript SDK

const executions = await client.executions.list({
  agentId: 'your-agent-id',
  status: 'completed',
  page: 1,
  limit: 20,
})

Execution Response Fields

FieldTypeDescription
idKSUIDUnique execution identifier
agent_idKSUIDThe agent that was executed
agent_version_idKSUIDThe specific agent version used
workspace_idKSUIDWorkspace scope
user_idKSUIDUser who initiated the execution (if authenticated)
session_idstringChat session ID (if applicable)
statusstringCurrent execution status
inputJSONInput provided to the agent
outputJSONResult produced by the agent
errorstringError message (if failed)
metadataJSONCustom metadata
token_usageJSONToken consumption breakdown
costfloatTotal cost in USD
duration_msintegerTotal duration in milliseconds
trace_idstringLink to the execution trace
started_attimestampWhen execution started
completed_attimestampWhen execution finished
created_attimestampWhen the execution record was created