Skip to main content
Glama

Get run result

get_run_result
Read-only

Retrieve a Plori run's current state by run_id to check status, progress, outputs, files, errors, or wait for completion or input.

Instructions

Get a run's current state by run_id. Every result has the run's status, timing, and attributed credits (micro-US-dollars) and tokens. A run that is still going also has last_worklog (the agent's latest note), last_tool_step, last_activity_at, tool_progress when it is recorded, and poll_after_seconds. A completed run has text (the agent's reply), a url to its conversation in the Plori web app, and files: the files the reply linked, as absolute URLs readable with the same bearer token as this call. Those links read the run's copy while file_source.state is pending and the saved revision once it is ready; save_failure is present when the save failed, and then the files are not durable. When file_source.source is agent_current_files, the links read the agent's current files, which later runs can change. A failed or cancelled run has cause, retryable and an error object that states what happened and whether the run was charged. A run with status "awaiting_input" lists its approval requests and questions, each approval request with an approve_url. After a request is answered, input_status is answered and continuation_run_id names the run that continues the task; input_status cancelled or expired means this run will not continue. An interrupted run that the platform resumed has resume_run_id.

Input Schema

NameRequiredDescriptionDefault
waitNotrue: hold this call until the run finishes, pauses for a person, or the hold ends (25 seconds by default, 50 seconds for Codex, up to 30 minutes for Claude Code 2.1.212 or later, at most 50 seconds without an MCP progressToken), then return the current state. false or omitted: return the current state at once.
run_idYesThe run_id to read: from a run result, continuation_run_id or resume_run_id.
agent_idNoThe agent that ran the run (agent_id in the result that returned the run_id). Give this or workspace_id.
wait_secondsNoHold length in seconds when wait is true, used instead of the client default. 0 or omitted uses the client default. A call without an MCP progressToken is still held at most 50 seconds.
workspace_idNoThe Workspace the run belongs to. Give this or agent_id; with both, agent_id is used.

Output Schema

NameRequiredDescriptionDefault
urlNoA deep link to this run's session in the plori web app.
hintNoWhat to do next with this run, in one sentence. Present only while the run is non-terminal.
textNoThe assistant's reply once the run has finished. While a run is still going this is the run's own status message, not an answer, and is often absent — read last_worklog and last_tool_step instead.
causeNoMachine-readable cause for a non-normal terminal state.
errorNoWhy a terminal error or cancelled run failed, whether it was charged and what to do about it. Absent for a run that is still going or that finished normally.
filesNoFiles in the Workspace files that this reply linked, in the order they appear. Each url is fetchable with the bearer token you called this tool with. Absent when the reply linked none.
run_idYesThe public run identifier; empty for an answered message whose continuation has not started.
statusYesThe current run status, queued/steering for a message accepted into an active conversation, or answered when the answer is recorded but its continuation has not started.
tokensNoAttributed token count; null when attribution is unavailable.
advisorNoAdvisor calls used and allowed, spend this turn, and its optional spend cap in micro-US-dollars.
creditsNoAttributed spend in micro-US-dollars; null when attribution is unavailable.
agent_idNoThe agent that runs the run. get_run_result and cancel_run take this value or workspace_id.
ended_atNoWhen the run reached a terminal state.
steer_idNoDurable message receipt when status is queued or steering. run_id names the running or paused predecessor, not a result of this message; find the later queued turn with list_runs.
retryableNoWhether sending the same message again could plausibly succeed. A time_limit run can continue with a follow-up message.
session_idYesThe durable conversation/session identifier.
started_atNoWhen the run started.
file_sourceNoWhere this run's file links read from and whether its files are saved. Execution status does not report the save; check state here.
stop_reasonNoController-selected stop reason, when present.
input_statusNoThe durable status of this run's human-input request, when it has one: pending, answered, cancelled or expired. cancelled and expired are terminal — that run will never resume, so stop polling it.
last_worklogNoThe agent's most recent one-sentence note about what it is doing, from the run's durable event log. Absent for a terminal result and for a run that has written none.
save_failureNoPresent when saving the run's working copy failed, so its files are not durable outputs. code names the failure. content_refusals lists up to three refused paths, relative to the copy root, each with its cause: hardlink, database_backup_required (a SQLite file that needs sqlite3 .backup) or unsupported_file_mode.
workspace_idNoThe Workspace UUID.
input_expiredNoTrue when this run is paused on a question its conversation has already moved past: a later run in the same conversation has completed. Do not answer it; start a new run instead.
poll_after_msNoThe same wait as poll_after_seconds, in milliseconds.
resume_run_idNoThe exact auto-resume successor for an interrupted run; poll this run next.
resume_statusNoAuto-resume disposition for an interrupted run: pending, resumed, failed, or unknown.
tool_progressNoDurable tool execution progress; absent when this run has no tool-progress telemetry.
usage_by_roleNoAttributed spend, tokens, and model-call counts split into executor, advisor, and reviewer roles.
last_tool_stepNoWhat this run last did with a tool: "running <tool>" while a call is in flight, otherwise "completed <tool>" for the most recent finished call. Absent for a terminal result and for a run with no tool-progress telemetry.
pending_inputsNoHuman inputs blocking an awaiting_input run.
elapsed_secondsNoSeconds since the run started; absent for a terminal result.
upstream_statusNoThe model provider's HTTP status when this run died on an upstream fault; absent otherwise.
last_activity_atNoWhen the run last wrote a note or finished a tool call. Absent for a terminal result and for a run that has done neither.
last_heartbeat_atNoMost recent durable executor heartbeat.
continuation_errorNoWhy the answered message has not started its continuation.
poll_after_secondsNoSuggested seconds before polling again, paced to this run's recent tool-completion rate; absent for a terminal result.
continuation_run_idNoThe exact continuation created for an answered input; poll this run next.
continuation_pendingNoThe answer was recorded and its continuation has not started yet. Retry this message with the same idempotency key to get the continuation.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed25 schema fields changedv0.17.1
    • changedInput schema / properties / agent_id / description
      Previous value: -"The agent's UUID."New value: +"The agent that ran the run (agent_id in the result that returned the run_id). Give this or workspace_id."
    • changedInput schema / properties / run_id / description
      Previous value: -"The run id returned by invoke_agent."New value: +"The run_id to read: from a run result, continuation_run_id or resume_run_id."
    • changedInput schema / properties / wait / description
      Previous value: -"When true, wait for a terminal result or human input (see this tool's description for how long the hold lasts). After this tool returns, continue polling while status is non-terminal; it cannot wake an idle client."New value: +"true: hold this call until the run finishes, pauses for a person, or the hold ends (25 seconds by default, 50 seconds for Codex, up to 30 minutes for Claude Code 2.1.212 or later, at most 50 seconds without an MCP progressToken), then return the current state. false or omitted: return the current state at once."
    • changedInput schema / properties / wait_seconds / description
      Previous value: -"Optional: how many seconds to wait when wait=true (maximum 1800). Omit to use the window your MCP client can hold."New value: +"Hold length in seconds when wait is true, used instead of the client default. 0 or omitted uses the client default. A call without an MCP progressToken is still held at most 50 seconds."
    • addedInput schema / properties / workspace_id
      Added value: +{
      +  "description": "The Workspace the run belongs to. Give this or agent_id; with both, agent_id is used.",
      +  "type": "string"
      +}
    • changedInput schema / required
      Previous value: -[
      -  "agent_id",
      -  "run_id"
      -]New value: +[
      +  "run_id"
      +]
    • addedOutput schema / properties / agent_id
      Added value: +{
      +  "description": "The agent that runs the run. get_run_result and cancel_run take this value or workspace_id.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / continuation_error
      Added value: +{
      +  "description": "Why the answered message has not started its continuation.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / continuation_pending
      Added value: +{
      +  "description": "The answer was recorded and its continuation has not started yet. Retry this message with the same idempotency key to get the continuation.",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / file_source
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Where this run's file links read from and whether its files are saved. Execution status does not report the save; check state here.",
      +  "properties": {
      +    "agent_id": {
      +      "description": "The Agent whose current files a pre-conversion run's links read.",
      +      "type": "string"
      +    },
      +    "saved_operation_id": {
      +      "description": "The save operation that produced saved_revision_id.",
      +      "type": "string"
      +    },
      +    "saved_revision_id": {
      +      "description": "The immutable revision the run's copy was saved as. Empty until the save is ready.",
      +      "type": "string"
      +    },
      +    "source": {
      +      "description": "agent_current_files for a pre-conversion run: links read the Agent's mutable current files, and later edits change their bytes. Absent for a Workspace run.",
      +      "type": "string"
      +    },
      +    "state": {
      +      "description": "Where this run's file links read from. pending: the run's exact working copy, while its save is in progress. ready: the immutable saved revision for a Workspace run, or the Agent's current files when source is agent_current_files. failed: the save failed; see save_failure. unavailable: no readable source is recorded. expired: the saved revision was deleted or the run's history expired.",
      +      "type": "string"
      +    },
      +    "working_copy_id": {
      +      "description": "The working copy the run executed on.",
      +      "type": "string"
      +    },
      +    "workspace_id": {
      +      "description": "The Workspace a Workspace run executed in.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "state"
      +  ],
      +  "type": [
      +    "null",
      +    "object"
      +  ]
      +}
    • changedOutput schema / properties / files / description
      Previous value: -"Files on the agent's disk that this reply linked, in the order they appear. Each url is fetchable with the bearer token you called this tool with. Absent when the reply linked none."New value: +"Files in the Workspace files that this reply linked, in the order they appear. Each url is fetchable with the bearer token you called this tool with. Absent when the reply linked none."
    • changedOutput schema / properties / files / items / properties / path / description
      Previous value: -"The file's path on the agent's disk, rooted at the disk root."New value: +"The file's path in the Workspace files, rooted at the Workspace root."
    • changedOutput schema / properties / files / items / properties / url / description
      Previous value: -"An absolute URL that streams the file's bytes, text or binary and of any size, with its own content type. Fetch it with the same bearer token you called this tool with."New value: +"An absolute URL that streams the file's bytes, text or binary and of any size, with its own content type. Fetch it with the same bearer token you called this tool with. Absent when file_source.state is failed, unavailable or expired: the file has no readable source."
    • changedOutput schema / properties / files / items / required
      Previous value: -[
      -  "path",
      -  "url"
      -]New value: +[
      +  "path"
      +]
    • changedOutput schema / properties / input_expired / description
      Previous value: -"True when this run is parked on a question its session has already moved past: a later run in the same conversation has completed. Do not answer it; start a new run instead."New value: +"True when this run is paused on a question its conversation has already moved past: a later run in the same conversation has completed. Do not answer it; start a new run instead."
    • addedOutput schema / properties / pending_inputs / items / properties / assigned_to
      Added value: +{
      +  "additionalProperties": false,
      +  "properties": {
      +    "email": {
      +      "type": "string"
      +    },
      +    "user_id": {
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "user_id",
      +    "email"
      +  ],
      +  "type": [
      +    "null",
      +    "object"
      +  ]
      +}
    • addedOutput schema / properties / pending_inputs / items / properties / open_to_members_at
      Added value: +{
      +  "type": [
      +    "null",
      +    "string"
      +  ]
      +}
    • changedOutput schema / properties / pending_inputs / items / required
      Previous value: -[
      -  "tool_call_id",
      -  "kind",
      -  "prompt"
      -]New value: +[
      +  "assigned_to",
      +  "tool_call_id",
      +  "kind",
      +  "prompt"
      +]
    • changedOutput schema / properties / poll_after_ms / description
      Previous value: -"Legacy spelling of poll_after_seconds in milliseconds; the two always agree. Prefer poll_after_seconds."New value: +"The same wait as poll_after_seconds, in milliseconds."
    • changedOutput schema / properties / retryable / description
      Previous value: -"Whether sending the same message again could plausibly succeed. False for a cause the same request would hit again, including time_limit — split the work or raise max_turn_seconds instead of retrying it unchanged."New value: +"Whether sending the same message again could plausibly succeed. A time_limit run can continue with a follow-up message."
    • changedOutput schema / properties / run_id / description
      Previous value: -"The public run identifier."New value: +"The public run identifier; empty for an answered message whose continuation has not started."
    • addedOutput schema / properties / save_failure
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Present when saving the run's working copy failed, so its files are not durable outputs. code names the failure. content_refusals lists up to three refused paths, relative to the copy root, each with its cause: hardlink, database_backup_required (a SQLite file that needs sqlite3 .backup) or unsupported_file_mode.",
      +  "properties": {
      +    "code": {
      +      "type": "string"
      +    },
      +    "content_refusals": {
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "cause": {
      +            "type": "string"
      +          },
      +          "path": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "cause",
      +          "path"
      +        ],
      +        "type": "object"
      +      },
      +      "type": [
      +        "null",
      +        "array"
      +      ]
      +    }
      +  },
      +  "required": [
      +    "code"
      +  ],
      +  "type": [
      +    "null",
      +    "object"
      +  ]
      +}
    • changedOutput schema / properties / status / description
      Previous value: -"The current run status."New value: +"The current run status, queued/steering for a message accepted into an active conversation, or answered when the answer is recorded but its continuation has not started."
    • addedOutput schema / properties / steer_id
      Added value: +{
      +  "description": "Durable message receipt when status is queued or steering. run_id names the running or paused predecessor, not a result of this message; find the later queued turn with list_runs.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / workspace_id
      Added value: +{
      +  "description": "The Workspace UUID.",
      +  "type": "string"
      +}
  2. Changed1 schema field changedv0.17.0
    • addedOutput schema / properties / pending_inputs / items / properties / approve_url
      Added value: +{
      +  "type": "string"
      +}
  3. Changed3 schema fields changedv0.16.2
    • addedOutput schema / properties / advisor
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Advisor calls used and allowed, spend this turn, and its optional spend cap in micro-US-dollars.",
      +  "properties": {
      +    "calls_allowed": {
      +      "type": "integer"
      +    },
      +    "calls_used": {
      +      "type": "integer"
      +    },
      +    "spend_cap_micro_usd": {
      +      "type": [
      +        "null",
      +        "integer"
      +      ]
      +    },
      +    "spend_micro_usd": {
      +      "description": "Gross advisor consumption for the turn; the cap compares against this amount.",
      +      "type": "integer"
      +    }
      +  },
      +  "required": [
      +    "calls_used",
      +    "calls_allowed",
      +    "spend_micro_usd"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / properties / error / properties / upgrade
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Which plan lifts the limit this run ended at, when it ended at one.",
      +  "properties": {
      +    "anonymous": {
      +      "type": "boolean"
      +    },
      +    "limit": {
      +      "type": "string"
      +    },
      +    "message": {
      +      "type": "string"
      +    },
      +    "offer": {
      +      "additionalProperties": false,
      +      "properties": {
      +        "discount_code": {
      +          "type": "string"
      +        },
      +        "first_period_price_micro_usd": {
      +          "type": "integer"
      +        },
      +        "message": {
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "discount_code",
      +        "first_period_price_micro_usd",
      +        "message"
      +      ],
      +      "type": [
      +        "null",
      +        "object"
      +      ]
      +    },
      +    "plan": {
      +      "type": "string"
      +    },
      +    "remedies": {
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "kind": {
      +            "type": "string"
      +          },
      +          "limits": {
      +            "additionalProperties": false,
      +            "properties": {
      +              "disk_gb": {
      +                "type": "integer"
      +              },
      +              "max_active_workflows": {
      +                "type": "integer"
      +              },
      +              "max_agents": {
      +                "type": "integer"
      +              },
      +              "max_concurrent_runs": {
      +                "type": "integer"
      +              }
      +            },
      +            "required": [
      +              "max_concurrent_runs",
      +              "max_agents",
      +              "max_active_workflows",
      +              "disk_gb"
      +            ],
      +            "type": [
      +              "null",
      +              "object"
      +            ]
      +          },
      +          "message": {
      +            "type": "string"
      +          },
      +          "offer": {
      +            "additionalProperties": false,
      +            "properties": {
      +              "discount_code": {
      +                "type": "string"
      +              },
      +              "first_period_price_micro_usd": {
      +                "type": "integer"
      +              },
      +              "message": {
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "discount_code",
      +              "first_period_price_micro_usd",
      +              "message"
      +            ],
      +            "type": [
      +              "null",
      +              "object"
      +            ]
      +          },
      +          "plan": {
      +            "type": "string"
      +          },
      +          "url": {
      +            "type": "string"
      +          },
      +          "usd_cents_per_month": {
      +            "type": "integer"
      +          }
      +        },
      +        "required": [
      +          "kind",
      +          "message"
      +        ],
      +        "type": "object"
      +      },
      +      "type": [
      +        "null",
      +        "array"
      +      ]
      +    },
      +    "url": {
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "limit",
      +    "plan",
      +    "message",
      +    "remedies"
      +  ],
      +  "type": [
      +    "null",
      +    "object"
      +  ]
      +}
    • addedOutput schema / properties / usage_by_role
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Attributed spend, tokens, and model-call counts split into executor, advisor, and reviewer roles.",
      +  "properties": {
      +    "advisor": {
      +      "additionalProperties": false,
      +      "properties": {
      +        "calls": {
      +          "type": "integer"
      +        },
      +        "credits": {
      +          "type": "integer"
      +        },
      +        "tokens": {
      +          "type": "integer"
      +        }
      +      },
      +      "required": [
      +        "credits",
      +        "tokens",
      +        "calls"
      +      ],
      +      "type": "object"
      +    },
      +    "executor": {
      +      "additionalProperties": false,
      +      "properties": {
      +        "calls": {
      +          "type": "integer"
      +        },
      +        "credits": {
      +          "type": "integer"
      +        },
      +        "tokens": {
      +          "type": "integer"
      +        }
      +      },
      +      "required": [
      +        "credits",
      +        "tokens",
      +        "calls"
      +      ],
      +      "type": "object"
      +    },
      +    "reviewer": {
      +      "additionalProperties": false,
      +      "properties": {
      +        "calls": {
      +          "type": "integer"
      +        },
      +        "credits": {
      +          "type": "integer"
      +        },
      +        "tokens": {
      +          "type": "integer"
      +        }
      +      },
      +      "required": [
      +        "credits",
      +        "tokens",
      +        "calls"
      +      ],
      +      "type": "object"
      +    }
      +  },
      +  "required": [
      +    "executor",
      +    "advisor",
      +    "reviewer"
      +  ],
      +  "type": [
      +    "null",
      +    "object"
      +  ]
      +}
  4. Changed3 schema fields changedv0.16.0
    • addedInput schema / properties / wait
      Added value: +{
      +  "description": "When true, wait for a terminal result or human input (see this tool's description for how long the hold lasts). After this tool returns, continue polling while status is non-terminal; it cannot wake an idle client.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / wait_seconds
      Added value: +{
      +  "description": "Optional: how many seconds to wait when wait=true (maximum 1800). Omit to use the window your MCP client can hold.",
      +  "maximum": 1800,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "properties": {
      +    "cause": {
      +      "description": "Machine-readable cause for a non-normal terminal state.",
      +      "type": "string"
      +    },
      +    "continuation_run_id": {
      +      "description": "The exact continuation created for an answered input; poll this run next.",
      +      "type": "string"
      +    },
      +    "credits": {
      +      "description": "Attributed spend in micro-US-dollars; null when attribution is unavailable.",
      +      "type": [
      +        "null",
      +        "integer"
      +      ]
      +    },
      +    "elapsed_seconds": {
      +      "description": "Seconds since the run started; absent for a terminal result.",
      +      "type": "integer"
      +    },
      +    "ended_at": {
      +      "description": "When the run reached a terminal state.",
      +      "type": [
      +        "null",
      +        "string"
      +      ]
      +    },
      +    "error": {
      +      "additionalProperties": false,
      +      "description": "Why a terminal error or cancelled run failed, whether it was charged and what to do about it. Absent for a run that is still going or that finished normally.",
      +      "properties": {
      +        "class": {
      +          "description": "The failure class: the run's terminal cause, or \"unknown\" when none was recorded.",
      +          "type": "string"
      +        },
      +        "message": {
      +          "description": "What happened, and whether the work was charged.",
      +          "type": "string"
      +        },
      +        "next_step": {
      +          "description": "What to do about it.",
      +          "type": "string"
      +        },
      +        "retryable": {
      +          "description": "Whether sending the same message again could plausibly succeed.",
      +          "type": "boolean"
      +        }
      +      },
      +      "required": [
      +        "class",
      +        "message",
      +        "retryable",
      +        "next_step"
      +      ],
      +      "type": [
      +        "null",
      +        "object"
      +      ]
      +    },
      +    "files": {
      +      "description": "Files on the agent's disk that this reply linked, in the order they appear. Each url is fetchable with the bearer token you called this tool with. Absent when the reply linked none.",
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "path": {
      +            "description": "The file's path on the agent's disk, rooted at the disk root.",
      +            "type": "string"
      +          },
      +          "url": {
      +            "description": "An absolute URL that streams the file's bytes, text or binary and of any size, with its own content type. Fetch it with the same bearer token you called this tool with.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "path",
      +          "url"
      +        ],
      +        "type": "object"
      +      },
      +      "type": [
      +        "null",
      +        "array"
      +      ]
      +    },
      +    "hint": {
      +      "description": "What to do next with this run, in one sentence. Present only while the run is non-terminal.",
      +      "type": "string"
      +    },
      +    "input_expired": {
      +      "description": "True when this run is parked on a question its session has already moved past: a later run in the same conversation has completed. Do not answer it; start a new run instead.",
      +      "type": "boolean"
      +    },
      +    "input_status": {
      +      "description": "The durable status of this run's human-input request, when it has one: pending, answered, cancelled or expired. cancelled and expired are terminal — that run will never resume, so stop polling it.",
      +      "type": "string"
      +    },
      +    "last_activity_at": {
      +      "description": "When the run last wrote a note or finished a tool call. Absent for a terminal result and for a run that has done neither.",
      +      "type": [
      +        "null",
      +        "string"
      +      ]
      +    },
      +    "last_heartbeat_at": {
      +      "description": "Most recent durable executor heartbeat.",
      +      "type": [
      +        "null",
      +        "string"
      +      ]
      +    },
      +    "last_tool_step": {
      +      "description": "What this run last did with a tool: \"running <tool>\" while a call is in flight, otherwise \"completed <tool>\" for the most recent finished call. Absent for a terminal result and for a run with no tool-progress telemetry.",
      +      "type": "string"
      +    },
      +    "last_worklog": {
      +      "description": "The agent's most recent one-sentence note about what it is doing, from the run's durable event log. Absent for a terminal result and for a run that has written none.",
      +      "type": "string"
      +    },
      +    "pending_inputs": {
      +      "description": "Human inputs blocking an awaiting_input run.",
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "consent_tool": {
      +            "type": "string"
      +          },
      +          "kind": {
      +            "type": "string"
      +          },
      +          "prompt": {
      +            "type": "string"
      +          },
      +          "risk": {
      +            "type": "string"
      +          },
      +          "tool_call_id": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "tool_call_id",
      +          "kind",
      +          "prompt"
      +        ],
      +        "type": "object"
      +      },
      +      "type": [
      +        "null",
      +        "array"
      +      ]
      +    },
      +    "poll_after_ms": {
      +      "description": "Legacy spelling of poll_after_seconds in milliseconds; the two always agree. Prefer poll_after_seconds.",
      +      "type": "integer"
      +    },
      +    "poll_after_seconds": {
      +      "description": "Suggested seconds before polling again, paced to this run's recent tool-completion rate; absent for a terminal result.",
      +      "type": "integer"
      +    },
      +    "resume_run_id": {
      +      "description": "The exact auto-resume successor for an interrupted run; poll this run next.",
      +      "type": "string"
      +    },
      +    "resume_status": {
      +      "description": "Auto-resume disposition for an interrupted run: pending, resumed, failed, or unknown.",
      +      "type": "string"
      +    },
      +    "retryable": {
      +      "description": "Whether sending the same message again could plausibly succeed. False for a cause the same request would hit again, including time_limit — split the work or raise max_turn_seconds instead of retrying it unchanged.",
      +      "type": [
      +        "null",
      +        "boolean"
      +      ]
      +    },
      +    "run_id": {
      +      "description": "The public run identifier.",
      +      "type": "string"
      +    },
      +    "session_id": {
      +      "description": "The durable conversation/session identifier.",
      +      "type": "string"
      +    },
      +    "started_at": {
      +      "description": "When the run started.",
      +      "type": [
      +        "null",
      +        "string"
      +      ]
      +    },
      +    "status": {
      +      "description": "The current run status.",
      +      "type": "string"
      +    },
      +    "stop_reason": {
      +      "description": "Controller-selected stop reason, when present.",
      +      "type": "string"
      +    },
      +    "text": {
      +      "description": "The assistant's reply once the run has finished. While a run is still going this is the run's own status message, not an answer, and is often absent — read last_worklog and last_tool_step instead.",
      +      "type": "string"
      +    },
      +    "tokens": {
      +      "description": "Attributed token count; null when attribution is unavailable.",
      +      "type": [
      +        "null",
      +        "integer"
      +      ]
      +    },
      +    "tool_progress": {
      +      "additionalProperties": false,
      +      "description": "Durable tool execution progress; absent when this run has no tool-progress telemetry.",
      +      "properties": {
      +        "active_tools": {
      +          "items": {
      +            "additionalProperties": false,
      +            "properties": {
      +              "id": {
      +                "type": "string"
      +              },
      +              "name": {
      +                "type": "string"
      +              },
      +              "started_at": {
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "id",
      +              "name",
      +              "started_at"
      +            ],
      +            "type": "object"
      +          },
      +          "type": [
      +            "null",
      +            "array"
      +          ]
      +        },
      +        "completed_count": {
      +          "type": "integer"
      +        },
      +        "last_completed_at": {
      +          "type": [
      +            "null",
      +            "string"
      +          ]
      +        }
      +      },
      +      "required": [
      +        "active_tools",
      +        "completed_count"
      +      ],
      +      "type": [
      +        "null",
      +        "object"
      +      ]
      +    },
      +    "upstream_status": {
      +      "description": "The model provider's HTTP status when this run died on an upstream fault; absent otherwise.",
      +      "type": "integer"
      +    },
      +    "url": {
      +      "description": "A deep link to this run's session in the plori web app.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "run_id",
      +    "session_id",
      +    "status"
      +  ],
      +  "type": "object"
      +}
  5. First observedv0.1.0

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well past the annotations (readOnlyHint, idempotentHint=false) with genuinely decision-relevant behavior: file links read the run's copy while state is pending and the saved revision once ready, files are non-durable when save_failure is present, and agent_current_files links are mutable by later runs. It does not contradict annotations. It stays at 4 because identity/scoping requirements (agent_id vs workspace_id) and the polling contract are left to the schema rather than restated here.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose is front-loaded in the first sentence, then the text is organized by run state, which mirrors how an agent will branch on the result. It is dense and long, and the extended enumeration of completed-run fields overlaps the existing output schema, so a little could be trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers every terminal and non-terminal state (running, completed, failed/cancelled, awaiting_input, interrupted/resumed) plus the durability caveats on file links, which is what an agent needs to interpret a result and choose its next call. Nothing material is missing for a read-by-id tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so wait, wait_seconds, agent_id and workspace_id are fully documented in structured fields. The description only echoes 'by run_id' and adds no syntax or selection detail beyond the schema, which is the baseline 3 case.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with its identifier: 'Get a run's current state by run_id.' That cleanly separates it from list_runs (many runs) and from get_credits/get_workspace_costs (aggregate billing rather than a single run's attributed credits). An agent can pick it without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied through state descriptions: poll a running run using poll_after_seconds, answer approvals when status is 'awaiting_input' (which points toward answer_pending_input), follow continuation_run_id or resume_run_id. But no sibling is ever named and there is no explicit when-to-use/when-not statement, so the routing must be inferred.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.