Plori
OfficialThis server is Plori's remote MCP API for managing persistent cloud AI agents, their runs, workflows, approvals, and account usage.
Agents: list, get, create-or-get by name, delete, and set an agent's model.
Runs: invoke an agent with a message (blocking or async), get run results, list run history, cancel in-flight runs, and schedule one-shot deferred runs.
Human-in-the-loop: list runs waiting for approval/input and answer those pending requests (approve/deny/provide value, optionally with a standing allow).
Workflows: create, list, get, edit, version, assign to an agent, run, and inspect workflow executions and per-step payloads.
Account: check credit balance, usage breakdown, disk usage, and list third-party OAuth connections.
plori
plori (plori.ai): a cloud AI agent with its own persistent environment - durable disk, real CLI tools, and memory.
plori provides the agent: each one gets a persistent machine with a real disk, real tools, and memory of its own. Idle agents scale to zero. You talk to your agents in the web app, or drive them from your own tools over MCP and REST.
This repository is the integration front door. The product itself lives at
plori.ai; the remote MCP server lives at https://api.plori.ai/mcp.
Connect your MCP client
plori is a remote MCP server (streamable HTTP). There is nothing to install or run locally. Sign-in happens in your browser via OAuth 2.1 the first time your client connects; headless environments can use an API key instead.
Claude Code
Paste this into your Claude Code conversation:
Set up https://plori.ai/SKILL.md
Claude reads the setup instructions and configures MCP if needed. If the new server
has not loaded, type /reload-plugins when Claude asks, then continue in the same
conversation. With pairing, open the short address Claude shows, enter the code,
sign in, and approve. You can use a phone while Claude Code runs on a remote machine.
No installed skill or plugin is required.
Cursor
Use the one-click Add to Cursor button, or add manually:
Settings -> MCP -> Add server with URL https://api.plori.ai/mcp.
VS Code
code --add-mcp '{"name":"plori","type":"http","url":"https://api.plori.ai/mcp"}'Codex CLI
codex mcp add plori --url https://api.plori.ai/mcp
codex mcp login ploriCodex auto-detects plori's OAuth on login. One-install alternative with the skill
bundled: codex plugin marketplace add plori-ai/codex-plugin then codex plugin add plori@plori.
Cline
Follow llms-install.md, written for Cline's automated installer.
Any other client
Native streamable-HTTP clients connect to https://api.plori.ai/mcp directly. Clients
that only speak stdio can bridge with the plori-mcp npm package
(a thin wrapper around mcp-remote with the endpoint pinned; this repository is its source):
npx plori-mcp
# headless / CI: authenticate with an API key instead of the OAuth flow
npx plori-mcp --header "Authorization: Bearer plori_sk_..."
# equivalent, without the wrapper:
npx mcp-remote https://api.plori.ai/mcpAPI keys are minted in Dashboard -> Settings on a registered account.
Related MCP server: openpouch
Or skip MCP: your own terminal
The plori CLI is not an MCP client. It is a door of its own, and it opens the same live session the web app shows: the recent history, a prompt, streaming output, and the approval queue in one place. A turn you send in the terminal appears in an open browser tab as it streams.
curl -fsSL https://plori.ai/install.sh | sh
plori login && plori attach <agent-name>The installer drops one static binary in ~/.local/bin and needs no Node; if that
directory is not on your PATH yet, the script prints the line to add. npm i -g @plori/cli works too. The argument to attach is an agent name, an agent id, or a
session id, so a session id copied out of the web app works on its own. Ctrl-D
detaches and leaves the run going on the server.
The terminal does not give the agent access to your local files. The shell, the disk, and the files are the agent's own cloud environment.
Verify the connection
Ask your client:
List my plori agents and tell me how many credits I have left.
You should see list_agents and get_credits tool calls and a real answer.
What the tools do
The server exposes 25 tools in five groups.
Agents (the Plori Router picks each agent's model per task):
list_agents(your agents, with model and live session status),get_agent(one agent's name, type, model, and status, plus its mailbox of mail from other agents on the account),create_agent(get or create an agent by name, which reuses an existing agent of that name instead of making a duplicate),delete_agent(permanently delete an agent and revoke its disk).Runs:
invoke_agent(send a message and wait for the reply, withwait_secondsto set how long to hold,idempotency_keyto make a retry return the original run, andcallback_urlpluscallback_secretto post a signed status notification to your endpoint),get_run_result(a run's status, timestamps, credits, tokens, tool progress, and the reply once it finishes),list_runs(an agent's run history, most recent first),cancel_run(stop an in-flight run, which reportscancellingand thencancelled),schedule_run(invoke an agent once later, after a delay or at a timestamp).Human-in-the-loop:
list_pending_inputs(runs paused on an approval or an input request),answer_pending_input(approve, deny, or answer one, which starts a continuation run).Workflows:
list_workflows(every workflow, or one agent's withagent_id, or the unassigned ones withagent_id="none"),get_workflow(metadata and the step projection pinned for execution),get_workflow_version(one exact version's full definition and parameter values),create_workflow(an empty workflow on a manual, cron, or webhook trigger, for an agent to build),edit_workflow(a batch of constrained edits as one new draft, under compare-and-swap onbase_version),set_workflow_agent(assign one of your agents to a workflow, typically afterdelete_agentreports paused workflows orrun_workflowreturnsworkflow_agentless),run_workflow(run a built workflow now, as a real, billed execution),list_workflow_executions(recent executions with status, fault, trigger source, timing, and credits),get_workflow_execution(one execution's per-step input and output payloads).Account:
get_credits(balance and plan),get_usage(spend by meter and by agent),get_disk(included, purchased, and used bytes),empty_trash(permanently empty an agent's trash so deleted files stop counting against the disk; only while that agent's pod is asleep),list_connections(your third-party OAuth providers with status, authorization and expiry times, and the scopes configured for each, never tokens or client secrets).
A turn that is still running when the hold ends continues on the server:
invoke_agent returns a run_id with status running and a poll_after_seconds
delay, and you read the answer with get_run_result using wait=true (or your own
wait_seconds, up to 1800).
Costs: creating and running agents spends plori credits from your account. Reading (lists, results, balances) is free. The pricing page has the details. Revoke a client's access any time in your client's settings, or revoke the API key in Dashboard -> Settings.
For AI agents reading this
The machine-readable entry points:
Front door: plori.ai/agents.md
Site index: plori.ai/llms.txt
Skill: SKILL.md (index:
/.well-known/agent-skills/index.json)MCP server card:
https://api.plori.ai/mcp/server-cardOAuth discovery: RFC 9728 protected-resource metadata on
api.plori.ai, dynamic client registration supportedRegistry entry:
ai.plori/ploriin the official MCP Registry
Every page on plori.ai is also served as Markdown: append .md to the path or send
Accept: text/markdown.
Docs and support
Connect guide (per-client, kept current)
Questions: agent@plori.ai
Available Tools
25 toolsanswer_pending_inputAnswer pending questionADestructiveInspect
Answer a run that is paused on a human-input request (from list_pending_inputs). For an approval, set approved=true/false. For an input request, set value to the requested text. A successful answer starts a continuation run: the returned run_id is that new continuation run, not the parked run, and is the id to poll with get_run_result.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | An optional note recorded with the answer. | |
| scope | No | Set to "thread" to approve AND allow the rest of this conversation's writes to the same connection, method and host, instead of a standing grant. It expires after 24 hours and covers no other host, method or conversation. Only set it when the human said to stop being asked for the rest of this task; ignored without approved=true, and on a card that has no such scope. Cannot be combined with always_allow. | |
| value | No | For an input request: the value to supply. | |
| run_id | Yes | The parked run's id. | |
| approved | No | For an approval request: approve (true) or deny (false). | |
| always_allow | No | Approve AND stop asking for this tool on this agent (a standing grant). Only set it when the human explicitly said to stop being asked, and only on a row whose consent_tool is set; ignored without approved=true. Revoke via DELETE /v1/agents/{agent_id}/tool-consents/{tool}. | |
| tool_call_id | Yes | The tool_call_id of the pending request (from list_pending_inputs). | |
| max_turn_seconds | No | Optional soft wall-clock budget to preserve on the continuation run; it does not change the parked run or impose a hard deadline. |
Output Schema
| Name | Required | Description |
|---|---|---|
| run_id | No | The continuation run created by the answer. |
| status | Yes | Answer status. |
| already | No | Whether this request had already been answered. |
| session_id | No | The continuation run's session. |
| tool_call_id | Yes | The pending tool call that was answered. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses a non-obvious and critical behavior: a successful answer starts a continuation run, and the returned run_id refers to that new run, not the parked one, and should be polled via get_run_result. Since annotations already carry destructiveHint and readOnlyHint, the description does not need to repeat them, though it could have warned about double-answering or consent side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the first sentence states purpose and mode selection, and the second sentence delivers the essential continuation-run caveat. There is no filler or redundant exposition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich parameter schema, annotations, and output schema, the description covers the key non-obvious flow: the continuation run and which run_id to poll. Consent and budget parameters are left to the schema, which is acceptable because the schema documents them thoroughly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema description coverage, the schema already documents each parameter, but the description adds a helpful selection rule: use approved for approvals and value for input requests, and clarifies that run_id is the parked run and tool_call_id comes from list_pending_inputs. This goes slightly beyond a bare restatement, though most parameter-level detail remains in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the exact action (answer), the target (a run paused on a human-input request), and the source (list_pending_inputs). It also distinguishes the two modes, approval vs input, which differentiates it clearly from sibling tools like list_pending_inputs or cancel_run.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly identifies when to use the tool: when a run is paused on a human-input request from list_pending_inputs, and it gives branch-level guidance for approvals vs input requests. It does not explicitly state when not to use it or mention alternatives such as cancel_run, so it misses the top anchor.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cancel_runCancel runADestructiveInspect
Stop an in-flight agent run. Cancellation is asynchronous: a successful call returns status "cancelling"; poll get_run_result until the run becomes "cancelled". A run that already finished cannot be cancelled.
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | Yes | The run id returned by invoke_agent. | |
| agent_id | Yes | The agent's UUID. |
Output Schema
| Name | Required | Description |
|---|---|---|
| runId | Yes | The run whose cancellation was requested. |
| status | Yes | Cancellation request status. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing that cancellation is asynchronous, that a successful call returns status 'cancelling', and that the run must be polled until it becomes 'cancelled'. This gives the agent critical expectations about side effects and timing that annotations alone do not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences with no filler. The core purpose is front-loaded, followed by essential async behavior and a practical caveat. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter tool with a full input schema, output schema, and rich annotations, the description supplies the missing operational knowledge: async cancellation, status transition, and the terminal-state limitation. Nothing essential is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, with both run_id and agent_id already described meaningfully in the input schema. The description does not add parameter-level detail, but it does not need to because the schema already handles it. Baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Stop an in-flight agent run.' This clearly distinguishes cancellation from related siblings like invoke_agent or get_run_result. The scope is precise: it targets only runs that are actively in progress.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear usage context by specifying the operation is for in-flight runs and explicitly warns that finished runs cannot be cancelled. It also instructs the agent to poll get_run_result to observe the final state. However, it does not explicitly name alternative tools for finished runs or other scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_agentGet or create agentAIdempotentInspect
Get or create an agent by name: a persistent cloud environment running plori's agent, with its own disk, tools, and memory. Create one when the work should accumulate somewhere the user can return to: a project with files that build up, a repo to keep checked out, tools to install once and reuse, or a long job to hand off. You do not need one for a question you can answer yourself or for a one-off script with no state worth keeping. If the account already has an agent with this name, that agent is returned (marked "existing": true) instead of a duplicate — safe to call repeatedly, and the right way to reconnect to an agent you used before. Creation is subject to the account's agent-count limit. The Plori Router chooses the model for each task.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The agent's name. Reusing a previous name returns that existing agent. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | The Agent's unique identifier; pass it to other tools as agent_id. |
| url | No | This Agent's page in the plori web app. |
| name | Yes | The Agent's name, chosen by its owner and unique within the account. |
| model | Yes | The model slug this Agent is configured to use. Empty means no explicit choice, which is not the same as no model — read effective_model for what a run will actually use. |
| config | Yes | Arbitrary JSON owned by the producing engine. |
| moving | No | True while this Agent's files are being copied to a new disk; check storage_notice rather than a separate route for the outcome. |
| status | No | The live warm-session state: warming, ready, or sleeping; empty when no session is active. |
| backend | Yes | The compute backend this Agent runs on. |
| user_id | Yes | The identifier of the account that owns this Agent. |
| deleting | No | True while this Agent's disk is still being erased; offer no action on it besides retrying the deletion itself. |
| existing | No | Whether create_agent returned an existing same-name agent instead of creating one. |
| queued_at | No | When a still-warming attach was accepted; present only while it is queued for node capacity. |
| created_at | Yes | When the Agent was created. |
| last_run_at | No | When this Agent last started a run; absent when it has never run. |
| deleting_since | No | When the deletion was first requested; present only while deleting is true. |
| storage_notice | No | The one sentence, if any, telling the owner about a storage move that stopped; show it verbatim, not paraphrased. |
| effective_model | Yes | The model a run on this Agent will actually use. plori-auto means the hosted router chooses per turn. |
| advisor_max_spend_micro_usd | Yes | Optional maximum advisor-completion spend per turn in micro-US-dollars. Zero disables advisor completions; null leaves no spend cap. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate idempotentHint=true and destructiveHint=false. The description adds valuable behavioral context: returned agents are marked 'existing', safe repeated calls, account-level agent-count limits, and the Plori Router choosing the model. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and then expands logically into use cases, idempotency, limits, and routing. It is longer than minimal, but each section earns its place. Minor redundancy exists because 'safe to call repeatedly' partly repeats the idempotentHint annotation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a create-or-get tool: it explains the resource, when to use it, idempotency, account limits, and model selection. The output schema exists, so return values need not be described in the text. No critical operational detail appears missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents the name parameter and its reuse behavior. The description reiterates that reusing a name returns the existing agent but does not add materially new parameter-level detail, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool gets or creates an agent by name, and defines the agent as a persistent cloud environment with its own disk, tools, and memory. It differentiates from siblings by emphasizing reuse semantics ('If the account already has an agent with this name, that agent is returned'), though it does not explicitly name alternatives like get_agent or invoke_agent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance: persistent projects, checked-out repos, reusable tools, and long hand-off jobs. It also states when not to use it: simple questions or one-off scripts with no state worth keeping. This is strong, actionable guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_workflowCreate workflowAInspect
Create an empty workflow. Returns the new workflow, including its id and — for a webhook trigger — its hook URL. trigger_kind defaults to "manual" (run it on demand with run_workflow); "cron" needs a cron_expr; "webhook" mints a public hook URL. trigger_kind is not read from description: a schedule stated only there leaves the workflow manual. The build can still change it — when the owning agent gives the workflow a schedule or webhook trigger step, trigger_kind and cron_expr follow that step. A new workflow has no steps and cannot run until its owning agent builds them.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | A short name for the workflow. | |
| agent_id | No | Optional UUID of one of your agents to own the workflow. That agent is then the one that can build, edit, and run it from a chat; leave it out and the workflow stays unassigned until you set an owner. | |
| cron_expr | No | Cron schedule (required when trigger_kind is "cron"), e.g. "0 9 * * *". A 5-field cron or an @daily/@hourly descriptor, evaluated in UTC. | |
| description | No | Optional description of what the workflow does. It is prose for the reader; no field is derived from it. | |
| trigger_kind | No | Optional trigger: "manual" (default), "cron", or "webhook". The build can change it later: a schedule or webhook trigger step sets it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| engine | Yes | |
| status | Yes | |
| user_id | Yes | |
| agent_id | Yes | |
| hook_key | Yes | |
| cron_expr | Yes | |
| created_at | Yes | |
| updated_at | Yes | |
| description | Yes | |
| notify_pref | Yes | |
| next_fire_at | Yes | |
| trigger_kind | Yes | |
| paused_reason | No | |
| template_slug | No | |
| active_version | Yes | |
| current_version | Yes | |
| spend_cap_month | Yes | |
| agent_deleted_at | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial non-obvious behavior beyond the annotations: trigger_kind is not derived from the description field, the owning agent's build step can override trigger_kind and cron_expr, and the created workflow cannot run until steps are built. These are exactly the hidden behavioral traits an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence carries distinct value: purpose, return values, trigger behavior, the description-field gotcha, build mutability, and run-readiness. The most essential scoping statement ('empty workflow') is front-loaded, and there is no redundant filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description fully covers creation semantics, trigger variants, ownership/build constraints, and return values. Since an output schema is present, the response shape does not need to be spelled out here, and no critical operational gap remains.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds meaningful cross-parameter semantics: manual is the default trigger, cron makes cron_expr required, webhook generates a public URL, description is purely prose, and the build can later mutate trigger_kind and cron_expr. This goes well beyond the individual parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create an empty workflow') and immediately clarifies what it returns (new workflow id, hook URL for webhook triggers). It also distinguishes itself from built/runnable workflows by noting a new workflow has no steps and cannot run until built.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context on when to use it: run_workflow is referenced for manual execution, cron requires cron_expr, webhook mints a public hook URL, and a description-only schedule does not set trigger_kind. It does not explicitly name edit_workflow as the alternative for modifying workflows, so it stops short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_agentDelete agentADestructiveIdempotentInspect
Permanently delete an agent and revoke its disk. This cannot be undone. Workflows the agent built are NOT deleted — they belong to the account — but the ones that were live are paused, and none of them run again until you assign them to another agent.
| Name | Required | Description | Default |
|---|---|---|---|
| agent_id | Yes | The agent's UUID to delete. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | The successful HTTP status code from the underlying operation. |
| workflows_paused | No | How many workflows this agent had built and had running were paused by the deletion. They are not deleted: assign them to another agent to run them again. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though annotations already mark the tool as destructive and idempotent, the description adds significant behavioral context: deletion is permanent, disk is revoked, workflows are NOT deleted but are paused and will not run until reassigned. This goes well beyond the annotations and clarifies partial data preservation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The core action and irreversibility are front-loaded, and the workflow-related caveat is presented in a clear second sentence. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive tool with one parameter, the description fully covers the necessary context: irreversibility, disk revocation, workflow ownership, and runtime behavior of affected workflows. The output schema exists so return-value details are not required.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single parameter agent_id is already documented as 'The agent's UUID to delete.' The description adds no additional meaning beyond the schema, so the baseline score of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Permanently delete an agent and revoke its disk.' This clearly distinguishes the tool from siblings like create_agent, get_agent, and list_agents, and its scope is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context by explaining the consequences of deletion, especially how workflows are preserved but paused. It implies the alternative of assigning workflows to another agent, though it does not explicitly name set_workflow_agent or state when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edit_workflowEdit workflowADestructiveIdempotentInspect
Apply a batch of constrained edits as one new draft version under base_version compare-and-swap. Supported ops are set_params, add_step, remove_step, and add_router. Read the exact current definition with get_workflow_version first; a stale base_version is rejected instead of overwriting concurrent work. Editing does not activate the draft.
| Name | Required | Description | Default |
|---|---|---|---|
| ops | Yes | One or more edits applied atomically in order. | |
| workflow_id | Yes | The workflow's UUID. | |
| base_version | Yes | The workflow's current_version; the edit conflicts if it changed. |
Output Schema
| Name | Required | Description |
|---|---|---|
| version | Yes | The new draft version created by the edit. |
| resolved | No | External identifiers resolved while binding the edit. |
| projection | Yes | The value-light projection of the edited workflow definition. |
| workflow_id | Yes | The edited workflow. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint=true and idempotentHint=true. The description adds valuable behavioral context: the compare-and-swap versioning, rejection of stale bases, and the fact that the edit creates a draft without activation. These details go beyond the annotation hints and are not redundant.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler. The core action is front-loaded, followed by operational guidance (read first, stale rejection, no activation). Every sentence contributes to correct usage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the key constraints: atomic batch, version conflict handling, prerequisite read, and activation behavior. With a full input schema (100% coverage) and an output schema present, the description provides sufficient context for an agent to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all parameters and their purposes. The description adds only minimal extra meaning—confirming supported ops and explaining base_version's compare-and-swap role—but most of this is already present in the schema (e.g., base_version description says 'the edit conflicts if it changed'). Thus, it meets the baseline of 3 without significantly enhancing parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool applies a batch of constrained edits as a new draft version, listing the supported ops (set_params, add_step, remove_step, add_router). It distinguishes itself from siblings like create_workflow, delete_agent, and get_workflow by focusing on editing an existing workflow with a compare-and-swap mechanism.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs the agent to read the current definition with get_workflow_version first, and warns that a stale base_version is rejected. It also clarifies that editing does not activate the draft, setting clear expectations for when to use this tool versus others.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
empty_trashEmpty agent trashADestructiveIdempotentInspect
Permanently empty one agent's trash. Deleting a file moves it into a trash that keeps counting against the account's disk until this is called — get_disk's trash_bytes says how much a call would free. Only works while the agent's pod is asleep: while it has run recently this returns an error asking you to wait for it to go idle (about two minutes with no run) or cancel the run first.
| Name | Required | Description | Default |
|---|---|---|---|
| agent_id | Yes | The agent's UUID whose trash to empty. |
Output Schema
| Name | Required | Description |
|---|---|---|
| disk | Yes | The account's disk state right after emptying, the same shape get_disk returns. |
| bytes_freed | Yes | Bytes freed from the account's shared disk by this call: the account's trash total before minus after when both get_disk reads reported one, otherwise the account's used_bytes before minus after. 0 when nothing was freed or when neither figure was available to diff — the storage worker's own purge result is an entry count, not a byte count, so it cannot supply this number. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and idempotentHint=true, but the description adds substantial behavioral nuance: it explains that trash counts against disk until emptied, how to predict the freed space via get_disk, and the error condition when the pod is active. This goes far beyond the annotations, providing a clear mental model of side effects and preconditions. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, each earning its place: the core purpose, the disk-impact rationale, and the operational constraint. It is front-loaded with the verb and resource, and the technical detail about pod-sleep state is presented immediately. No redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter destructive tool with an output schema, the description covers all necessary context: what it does, why it matters (disk space), how to check recoverable space, and the exact precondition (pod asleep) with a fallback instruction. An agent has everything needed to call it correctly and understand consequences.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter agent_id is fully documented in the schema (100% coverage) with a clear description ('The agent's UUID whose trash to empty'). The description does not add extra parameter-level meaning, but given the schema already covers it, a baseline 3 is appropriate. The description's context about the tool's behavior does not extend parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource ('Permanently empty one agent's trash') that precisely identifies the tool's action. It distinguishes itself from siblings like delete_agent and get_disk by explaining the trash mechanism and how get_disk reports the recoverable space. No ambiguity about what this tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context on when to use it (when trash is counting against disk, so you want to free space) and explicitly states a critical constraint: it only works while the agent's pod is asleep, with a concrete wait time (about two minutes) and an alternative (cancel the run). It does not explicitly list alternative tools to use instead, but the get_disk reference provides a natural alternative for checking before calling. This is strong enough guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_agentGet agent detailsARead-onlyInspect
Get one agent's details (name, type, model, status) by its id, and its mailbox: same-account mail from other agents, open letters first (accepted, delivering, blocked), then applied or undeliverable ones, newest within each group, capped at 20.
| Name | Required | Description | Default |
|---|---|---|---|
| agent_id | Yes | The agent's UUID (from list_agents or create_agent). |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | The Agent's unique identifier; pass it to other tools as agent_id. |
| url | No | This Agent's page in the plori web app. |
| name | Yes | The Agent's name, chosen by its owner and unique within the account. |
| model | Yes | The model slug this Agent is configured to use. Empty means no explicit choice, which is not the same as no model — read effective_model for what a run will actually use. |
| config | Yes | Arbitrary JSON owned by the producing engine. |
| moving | No | True while this Agent's files are being copied to a new disk; check storage_notice rather than a separate route for the outcome. |
| status | No | The live warm-session state: warming, ready, or sleeping; empty when no session is active. |
| backend | Yes | The compute backend this Agent runs on. |
| mailbox | Yes | This agent's mailbox letters, open ones (accepted, delivering, blocked) first, then applied or undeliverable ones, newest within each group, at most 20. |
| user_id | Yes | The identifier of the account that owns this Agent. |
| deleting | No | True while this Agent's disk is still being erased; offer no action on it besides retrying the deletion itself. |
| queued_at | No | When a still-warming attach was accepted; present only while it is queued for node capacity. |
| created_at | Yes | When the Agent was created. |
| last_run_at | No | When this Agent last started a run; absent when it has never run. |
| deleting_since | No | When the deletion was first requested; present only while deleting is true. |
| storage_notice | No | The one sentence, if any, telling the owner about a storage move that stopped; show it verbatim, not paraphrased. |
| effective_model | Yes | The model a run on this Agent will actually use. plori-auto means the hosted router chooses per turn. |
| advisor_max_spend_micro_usd | Yes | Optional maximum advisor-completion spend per turn in micro-US-dollars. Zero disables advisor completions; null leaves no spend cap. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description adds substantial behavioral detail: mailbox ordering (open letters first, then applied/undeliverable), grouping by status, newest within each group, and a cap of 20. This goes beyond the structured fields, though error/edge-case behavior is not addressed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one dense sentence with no filler; every clause earns its place, and the main purpose is front-loaded. It could be split into two sentences for readability, but it remains efficient and structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter tool with an output schema covering return structure, the description supplies all necessary behavioral context: the fields returned, mailbox ordering and grouping rules, and the cap. Nothing essential is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the agent_id description already explains its source and type. The description only adds 'by its id,' which is redundant with the schema and does not contribute additional semantic constraints or format details. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Get one agent's details'), identifies the resource by id, and enumerates the returned fields ('name, type, model, status') plus the mailbox. The singular 'one' and 'by its id' clearly distinguish it from list_agents and other sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It is clear that this tool is for retrieving a single agent when you already have its UUID, and the schema notes the id comes from list_agents or create_agent. It does not explicitly name alternatives or state when not to use it, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_creditsGet account balanceARead-onlyInspect
Get the authenticated account's US-dollar balance and plan. Running agents spends this prepaid balance, so check it before invoking. For where the money went, use get_usage instead. balance_usd is the dollar-formatted balance.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| packs | Yes | Credit packs this account can buy. Each pack's usd_cents is its price in US cents and its credits are what the purchase adds to balance. |
| plans | Yes | Subscription plans on offer, with their monthly credit grant. |
| limits | Yes | The caps this account's plan tier enforces. |
| balance | Yes | The account's remaining prepaid balance, in credits. 1,000,000 credits = 1 US dollar. |
| user_id | Yes | The identifier of the account this balance belongs to. |
| audience | Yes | |
| plan_tier | Yes | The plan tier this account resolves to: free, pro or power. An account with no active plan is free. |
| active_plan | Yes | The account's current subscription, or null when it has none and is on the free tier. |
| balance_usd | Yes | The account balance formatted in US dollars, without a currency symbol. |
| account_email | Yes | The email address of the account this balance belongs to. |
| can_manage_billing | Yes | |
| low_credit_threshold | Yes | The balance, in the same credits, below which this account is warned it is running low. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true, so the read-only nature is covered. The description adds useful context beyond the annotations: the balance is prepaid and is spent by running agents, making it important to check before invocation. This is valuable behavioral context for the caller.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, each earning its place: identifying the resource, warning about prepaid spend, directing to the sibling for usage details, and clarifying a returned field. The critical usage guidance is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only balance check with an output schema present, the description covers the purpose, when to call it, what the balance represents, and how it differs from the closely related sibling. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the input schema offers nothing to explain. The description adds relevant output field context by naming balance_usd and noting it is dollar-formatted, which helps the agent interpret results despite no parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get the authenticated account's US-dollar balance and plan.' It also distinguishes itself from the sibling get_usage by clarifying that get_credits is for checking balance, not for seeing where money went.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to use this tool ('check it before invoking' agents that spend prepaid balance) and names the alternative for a different need: 'For where the money went, use get_usage instead.' This fully routes the agent between siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_diskGet disk usageARead-onlyInspect
Get the authenticated account's disk state (included, purchased, used bytes, and monthly cost).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| used_bytes | Yes | |
| total_bytes | Yes | |
| trash_bytes | No | |
| usage_stale | No | True when a mount is holding one of the account's disks but has not reported its usage within the writer-lease lifetime. used_bytes is then the last figure that mount reported, not the current one — treat it as a floor and say so rather than quoting it as the account's usage. |
| warning_level | Yes | |
| included_bytes | Yes | |
| monthly_credits | Yes | |
| purchased_bytes | Yes | |
| usage_observed_at | No | When a mount last reported the used figure. Present only while a mount is holding one of the account's disks; when none is, nothing can be changing the figure and there is no reporting clock to quote. |
| storage_credits_per_gb | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the safe read-only nature is covered. The description adds useful scoping ('authenticated account's') and mentions monthly cost, but it does not disclose other behavioral details like response shape or potential delays; the output schema covers return format.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence contains all essential information without repetition or filler. Every phrase adds meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only tool with an output schema, the description is complete. An agent can correctly determine when and how to invoke this tool without additional context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters, so the baseline is 4. The description adds value by naming the output fields, which is sufficient for a parameterless tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Get') and resource ('disk state') and enumerates the exact data returned: included, purchased, used bytes, and monthly cost. This clearly distinguishes the tool from siblings like get_usage or get_credits.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use when you need the authenticated account's disk usage or cost, but it does not explicitly say when to use this tool versus alternatives such as get_usage. There is no exclusion or comparison to sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_run_resultGet run resultADestructiveInspect
Get a run's status, timing, attributed credits (micro-US-dollars) and tokens, and what it is doing while it runs: last_worklog (the agent's own most recent note), last_tool_step ("running ", or "completed " between calls), last_activity_at, and tool_progress (active calls, last completion time, completed-call count) when telemetry exists. With wait=true it holds your turn until the run finishes, pauses for input, or the hold ends (contract in the server instructions; wait_seconds bounds it). A completed run includes the reply text and a url to its session; files the reply linked come back as absolute URLs in the text and as a "files" list, fetched with the same bearer token you called this tool with. A failed or cancelled run includes its cause, whether it is retryable, and an "error" object saying what happened, whether the work was charged and what to do next. Status "awaiting_input" includes the pending request for answer_pending_input. Once that request is answered, input_status reads "answered" and continuation_run_id names the run to poll next; "cancelled" or "expired" means the run will never resume, so stop polling it. Keep polling a non-terminal run at poll_after_seconds.
| Name | Required | Description | Default |
|---|---|---|---|
| wait | No | 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. | |
| run_id | Yes | The run id returned by invoke_agent. | |
| agent_id | Yes | The agent's UUID. | |
| wait_seconds | No | Optional: how many seconds to wait when wait=true (maximum 1800). Omit to use the window your MCP client can hold. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | A deep link to this run's session in the plori web app. |
| hint | No | What to do next with this run, in one sentence. Present only while the run is non-terminal. |
| text | No | 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. |
| cause | No | Machine-readable cause for a non-normal terminal state. |
| error | No | 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. |
| files | No | 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. |
| run_id | Yes | The public run identifier. |
| status | Yes | The current run status. |
| tokens | No | Attributed token count; null when attribution is unavailable. |
| advisor | No | Advisor calls used and allowed, spend this turn, and its optional spend cap in micro-US-dollars. |
| credits | No | Attributed spend in micro-US-dollars; null when attribution is unavailable. |
| ended_at | No | When the run reached a terminal state. |
| retryable | No | 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. |
| session_id | Yes | The durable conversation/session identifier. |
| started_at | No | When the run started. |
| stop_reason | No | Controller-selected stop reason, when present. |
| input_status | No | 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. |
| last_worklog | No | 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. |
| input_expired | No | 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. |
| poll_after_ms | No | Legacy spelling of poll_after_seconds in milliseconds; the two always agree. Prefer poll_after_seconds. |
| resume_run_id | No | The exact auto-resume successor for an interrupted run; poll this run next. |
| resume_status | No | Auto-resume disposition for an interrupted run: pending, resumed, failed, or unknown. |
| tool_progress | No | Durable tool execution progress; absent when this run has no tool-progress telemetry. |
| usage_by_role | No | Attributed spend, tokens, and model-call counts split into executor, advisor, and reviewer roles. |
| last_tool_step | No | 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. |
| pending_inputs | No | Human inputs blocking an awaiting_input run. |
| elapsed_seconds | No | Seconds since the run started; absent for a terminal result. |
| upstream_status | No | The model provider's HTTP status when this run died on an upstream fault; absent otherwise. |
| last_activity_at | No | 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. |
| last_heartbeat_at | No | Most recent durable executor heartbeat. |
| poll_after_seconds | No | Suggested seconds before polling again, paced to this run's recent tool-completion rate; absent for a terminal result. |
| continuation_run_id | No | The exact continuation created for an answered input; poll this run next. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description is exceptionally detailed: it discloses the wait hold contract, terminal vs non-terminal states, error objects, retryability, file URL auth behavior, and the input_status lifecycle. Annotations signal destructive/open-world behavior, and the description doesn't contradict them, though it doesn't elaborate on what destructive side effect might exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long but dense and well-structured: core result fields come first, then wait behavior, then state-specific outputs, then polling guidance. Every sentence carries operational value with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex polling tool with an output schema, the description is complete: it covers success, failure, cancellation, awaiting input, authentication, file URLs, retryability, and polling cadence. An agent can correctly invoke and interpret results without needing additional documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds real meaning by explaining the wait hold contract, wait_seconds bound, and how agent_id/run_id relate to invoke_agent. It also clarifies the polling semantics of wait=true and the 'cannot wake an idle client' limitation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Get') and enumerates exactly what is returned: status, timing, credits, tokens, worklog, tool steps, activity, and progress. It clearly focuses on a single run's result, distinguishing it from sibling tools like list_runs, invoke_agent, and cancel_run.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit polling instructions ('Keep polling a non-terminal run at poll_after_seconds') and explains when to stop polling ('cancelled' or 'expired' means never resume). It also explains wait=true vs the client-held window, and implies that answer_pending_input is the path for 'awaiting_input', though it doesn't explicitly name the alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_usageGet usageARead-onlyInspect
Get the authenticated account's usage rollup (US-dollar spend by role, meter, and agent, with recent runs). Use this to answer where the money went; for the current balance use get_credits.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| tools | Yes | |
| agents | Yes | |
| totals | Yes | |
| by_kind | Yes | |
| by_role | Yes | |
| workflows | Yes | |
| recent_runs | Yes | |
| workflow_executions | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true, and the description adds useful behavior beyond that: the data is scoped to the authenticated account, aggregated as a rollup, and includes spend dimensions plus recent runs. It does not contradict the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences with no filler. The core purpose and included breakdown are front-loaded, and the sibling distinction is delivered in the second sentence without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only tool with an output schema, the description provides all essential context: account scope, aggregation type, spend dimensions, and when to choose a different tool. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is nothing for the description to clarify. Per the rubric, a zero-parameter tool gets a baseline of 4; the description correctly focuses on the output semantics instead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Get') with a clear resource: the authenticated account's usage rollup. It further specifies the breakdown ('US-dollar spend by role, meter, and agent') and 'recent runs', making its purpose distinct from the sibling get_credits.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use this tool: 'Use this to answer where the money went.' It also names the alternative for a different need: 'for the current balance use get_credits.' This is clear routing with no inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workflowGet workflowARead-onlyInspect
Get one workflow's metadata and step projection. The projection is the version pinned for execution (active_version), falling back to current_version for a draft that has not been activated.
| Name | Required | Description | Default |
|---|---|---|---|
| workflow_id | Yes | The workflow's UUID (from list_workflows or create_workflow). |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| engine | Yes | |
| status | Yes | |
| user_id | Yes | |
| agent_id | Yes | |
| hook_key | Yes | |
| cron_expr | Yes | |
| created_at | Yes | |
| projection | Yes | Arbitrary JSON owned by the producing engine. |
| updated_at | Yes | |
| description | Yes | |
| notify_pref | Yes | |
| next_fire_at | Yes | |
| trigger_kind | Yes | |
| paused_reason | No | |
| template_slug | No | |
| active_version | Yes | |
| current_version | Yes | |
| spend_cap_month | Yes | |
| agent_deleted_at | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the agent knows it is a safe read operation. The description adds valuable behavioral context: it explains the projection selection logic (active_version pinned for execution, with current_version fallback for drafts), which goes beyond the annotation and helps the agent understand what data will be returned.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with zero redundancy. The core purpose is front-loaded, followed by a clarifying explanation of the projection behavior. Every word earns its place, making it exceptionally concise and structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a single parameter, full schema coverage, presence of an output schema, and annotations covering the read-only safety profile, the description covers all essential aspects. The fallback logic for projections is explained, and nothing an agent needs to call the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameter 'workflow_id' is fully documented in the schema, including its source (list_workflows or create_workflow). The tool description adds no additional parameter guidance beyond the schema, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Get') and resource ('one workflow's metadata and step projection'), and the projection is clearly defined. It distinguishes itself from siblings like list_workflows (which lists all) and get_workflow_version (which fetches a specific version) by focusing on the active execution projection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly indicates when to use this tool (to retrieve metadata and the projection used for execution) and provides context on the projection fallback behavior. It does not explicitly name alternatives or exclusions, but the sibling list and context imply use cases, so it earns a 4 rather than a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workflow_executionGet workflow executionARead-onlyInspect
Get one workflow execution's status, billing, timing, credits, and full persisted per-step input/output payloads. fault explains why a non-succeeded execution ended. user means the workflow's own steps or limits. A platform fault is never billed. fault is null when the execution succeeded. billed is the billing flag. Use this tool to poll a run or inspect each step. list_workflow_executions omits step payloads.
| Name | Required | Description | Default |
|---|---|---|---|
| workflow_id | Yes | The workflow's UUID. | |
| execution_id | Yes | The execution's UUID (from run_workflow). |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| error | No | Arbitrary JSON owned by the producing engine. |
| fault | Yes | Why a non-succeeded execution ended. User means the workflow's own steps or limits. A platform fault is never billed. This field is null when the execution succeeded. |
| steps | No | Arbitrary JSON owned by the producing engine. |
| billed | Yes | The billing flag. True only for a user-fault succeeded, failed, or timed-out execution. |
| status | Yes | |
| credits | Yes | |
| ended_at | Yes | |
| created_at | Yes | |
| started_at | Yes | |
| step_stats | No | Arbitrary JSON owned by the producing engine. |
| duration_ms | Yes | |
| workflow_id | Yes | |
| trigger_source | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark readOnlyHint=true, and the description aligns with that. It adds valuable behavioral context beyond the annotations: fault semantics (user vs platform), billing implications (platform fault is never billed), and that fault is null on success. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The main purpose is front-loaded in the first sentence, and subsequent sentences efficiently explain fault and billing semantics. The only slight redundancy is 'billed is the billing flag,' which adds marginal value, but overall the description is tight and information-dense.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the description does not need to document return fields. It covers fault behavior, billing semantics, usage scenarios, and how it differs from a sibling tool. Nothing an agent needs to invoke the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters clearly. The description confirms the tool targets a single execution and references run_workflow, but it adds no new parameter-level syntax or format details. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the action 'Get' and the specific resource 'one workflow execution', enumerating the returned dimensions (status, billing, timing, credits, per-step payloads). It also distinguishes the tool from list_workflow_executions by noting that the sibling omits step payloads, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit usage guidance: 'Use this tool to poll a run or inspect each step.' It also names the relevant alternative, list_workflow_executions, and explains the key difference (omits step payloads), effectively telling the agent when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workflow_versionGet workflow versionARead-onlyInspect
Get one exact workflow version, including its full builder definition with step parameter values and its value-light projection. Use current_version from get_workflow unless you intentionally need an older version.
| Name | Required | Description | Default |
|---|---|---|---|
| version | Yes | The positive version number to retrieve. | |
| workflow_id | Yes | The workflow's UUID. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| author | Yes | |
| version | Yes | |
| created_at | Yes | |
| definition | No | Arbitrary JSON owned by the producing engine. |
| projection | No | Arbitrary JSON owned by the producing engine. |
| chat_run_id | Yes | |
| workflow_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the safe read behavior is covered. The description adds useful behavioral context by specifying exactly what the response includes—the full builder definition with step parameter values and the value-light projection—which goes beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences with no filler. The first states the core behavior and returned content, and the second gives routing guidance. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, two-parameter tool with complete schema descriptions and an output schema present, the description provides all needed calling context plus explicit guidance on when not to use it. Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema fully documents both workflow_id and version. The description does not add new parameter-level detail beyond the schema, which matches the baseline expectation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Get one exact workflow version' and explains what is included ('full builder definition with step parameter values and its value-light projection'). It also distinguishes itself from get_workflow by referencing 'current_version', so an agent can disambiguate the sibling tools without inspecting schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool versus the alternative: 'Use current_version from get_workflow unless you intentionally need an older version.' This gives a clear condition and names the alternative tool directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
invoke_agentInvoke agentADestructiveInspect
Send a message to an agent and return its reply, or a "running" run_id to poll with get_run_result. Use it for work that should outlive a single request: files written now and read later, software installed once and reused, a repo kept checked out, or a long job handed off. The hold and polling contract is in the server instructions: wait=false returns the run_id at once, wait_seconds bounds the hold, and agent turns can take minutes. A running result reports last_worklog, last_tool_step and last_activity_at; a completed one carries the reply text, files, credits (micro-US-dollars) and tokens; every result carries session_id (pass it back to continue the conversation) and a url a human can open. An account's plan caps how many runs it may have in flight at once across all its agents: over the cap returns 429, so wait for a run to finish and retry; turns on one agent are not queued for you. Pass idempotency_key when you might retry, or the retry starts and bills a second run. A run that pauses for a human returns status "awaiting_input" with the request inline; answer it with answer_pending_input. Cost scales with how much the agent has to explore: name the exact resources, fields and output format you want, and set max_turn_tokens for a bounded lookup.
| Name | Required | Description | Default |
|---|---|---|---|
| wait | No | Wait for the turn and return the reply (default true); the hold lasts as long as your client keeps the call open, or wait_seconds. Set false to return a run_id immediately and poll get_run_result — prefer this for long or tool-heavy turns so the call doesn't block your own turn. | |
| message | Yes | The message to send to the agent. | |
| agent_id | Yes | The agent's UUID. | |
| session_id | No | Optional thread/session id to continue an existing conversation (a previous invoke_agent or get_run_result result carries it as "session_id"); omit to start a new one. | |
| callback_url | No | Optional callback URL for this run. Must use http or https and resolve only to public addresses. | |
| wait_seconds | No | Optional: how many seconds to wait for the turn before returning a "running" run_id (maximum 1800). Omit to use the window your MCP client can hold. Ignored when wait=false. | |
| callback_secret | No | Optional secret used to sign callback deliveries with HMAC-SHA256. | |
| idempotency_key | No | Optional retry guard: a string you generate for this attempt. Re-sending the same key with the same agent and message within 24h returns the ORIGINAL run instead of starting a second one. Reusing a key with a different message is an error. | |
| max_turn_tokens | No | Optional cumulative cache-weighted token ceiling for this turn. 0 or omitted uses the agent's default of 2,000,000; the maximum is 5,000,000. The agent reserves its final 2% for a tool-free wrap-up. | |
| max_turn_seconds | No | Optional soft wall-clock budget for this turn in seconds, maximum 14,400. 0 or omitted uses the deployment's configured default, and where none is configured a turn has no wall-clock budget at all. It schedules an in-loop checkpoint and does not cancel the run. | |
| max_advisor_spend_micro_usd | No | Optional maximum advisor-completion spend for this turn in micro-US-dollars. 0 disables advisor completions. Omit it to use the agent setting; when neither is set, at most two advisor calls can run. The maximum is 5,000,000. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | A deep link to this run's session in the plori web app. |
| hint | No | What to do next with this run, in one sentence. Present only while the run is non-terminal. |
| text | No | 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. |
| cause | No | Machine-readable cause for a non-normal terminal state. |
| error | No | 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. |
| files | No | 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. |
| run_id | Yes | The public run identifier. |
| status | Yes | The current run status. |
| tokens | No | Attributed token count; null when attribution is unavailable. |
| advisor | No | Advisor calls used and allowed, spend this turn, and its optional spend cap in micro-US-dollars. |
| credits | No | Attributed spend in micro-US-dollars; null when attribution is unavailable. |
| ended_at | No | When the run reached a terminal state. |
| retryable | No | 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. |
| session_id | Yes | The durable conversation/session identifier. |
| started_at | No | When the run started. |
| stop_reason | No | Controller-selected stop reason, when present. |
| input_status | No | 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. |
| last_worklog | No | 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. |
| input_expired | No | 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. |
| poll_after_ms | No | Legacy spelling of poll_after_seconds in milliseconds; the two always agree. Prefer poll_after_seconds. |
| resume_run_id | No | The exact auto-resume successor for an interrupted run; poll this run next. |
| resume_status | No | Auto-resume disposition for an interrupted run: pending, resumed, failed, or unknown. |
| tool_progress | No | Durable tool execution progress; absent when this run has no tool-progress telemetry. |
| usage_by_role | No | Attributed spend, tokens, and model-call counts split into executor, advisor, and reviewer roles. |
| last_tool_step | No | 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. |
| pending_inputs | No | Human inputs blocking an awaiting_input run. |
| elapsed_seconds | No | Seconds since the run started; absent for a terminal result. |
| upstream_status | No | The model provider's HTTP status when this run died on an upstream fault; absent otherwise. |
| last_activity_at | No | 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. |
| last_heartbeat_at | No | Most recent durable executor heartbeat. |
| poll_after_seconds | No | Suggested seconds before polling again, paced to this run's recent tool-completion rate; absent for a terminal result. |
| continuation_run_id | No | The exact continuation created for an answered input; poll this run next. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only indicate safety hints; the description adds extensive behavioral detail: async return modes, rate cap semantics, idempotency with cost implications, human-pause status, and cost scaling. This goes far beyond the annotations and gives the agent a realistic model of how the tool behaves.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but this is an 11-parameter, complex tool with async semantics; nearly every sentence carries unique guidance. It is front-loaded with the core action and use cases, though the 'server instructions' mention and some redundancy with schema details keep it from a perfect conciseness score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a rich output schema and this description, nothing essential is missing: the agent knows the full workflow (invoke, poll, resume, handle human input), the result shape (running vs. completed), rate limits, idempotency, and cost factors. The addition of a human-readable URL and session continuity further completes the picture.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description adds strategic context beyond the schema for wait, wait_seconds, idempotency_key, session_id, and max_turn_tokens (e.g., 'the retry starts and bills a second run', 'set max_turn_tokens for a bounded lookup'). This elevates parameter understanding beyond mere field definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource: 'Send a message to an agent and return its reply, or a "running" run_id to poll with get_run_result.' It clearly identifies the tool's core action and scope, and the mention of get_run_result and answer_pending_input helps distinguish it from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance on when to use this tool: 'Use it for work that should outlive a single request' with concrete examples. It also names alternatives for follow-up actions (get_run_result for polling, answer_pending_input for human pauses) and warns about rate limiting and retry behavior, leaving no ambiguity about when to choose this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_agentsList agentsARead-onlyInspect
List the agents owned by the authenticated account, newest first, with each one's model, live session status, web page url and when it last ran. An agent whose model is empty is not unconfigured: effective_model says what a run will use, and plori-auto means the hosted router chooses per turn.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | The returned items, in the endpoint's documented order. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description adds meaningful behavioral detail: results are returned newest first, include a live session status and web page URL, and there is a non-obvious semantic distinction between an empty model and effective_model, including what plori-auto means. This is genuinely useful interpretive context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, each earning its place. The first sentence front-loads the action, scope, ordering, and output fields; the second adds an important caveat about interpreting the model field. No fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless read-only listing operation with an output schema available, the description is complete: it covers the scope, ordering, returned fields, and a key edge-case nuance. Nothing needed for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters and schema coverage is 100%, so there is no parameter documentation burden. The description appropriately focuses on output semantics rather than parameters, earning the baseline 4 for a parameterless tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('List'), names the resource ('agents'), and scopes it to the authenticated account. It also reveals the ordering ('newest first') and the returned fields, which clearly distinguishes it from sibling tools like get_agent, list_runs, and list_workflows.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The usage context is implied: call this when you need to list the account's agents. It does not explicitly contrast itself with get_agent or mention when not to use it, but the simple resource-oriented phrasing makes the primary use case reasonably clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_connectionsList connectionsARead-onlyInspect
List the authenticated account's third-party OAuth connections, including each provider's status, authorization and expiry times, and configured scopes. Read needs_reauth for whether a human has to go and reconnect one; status is the same fact spelled out (authorized needs no action, reconnect_needed and unauthorized do). Never derive it from expires_at: tokens refresh lazily when used, so an authorized row may have a past expires_at, and authorized with expires_at=null means the grant never expires. Token and client-secret material is never returned.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| connections | Yes | Third-party OAuth connection status records; never secret material. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description adds vital behavioral nuance: it explains how to interpret needs_reauth vs status, warns against deriving status from expires_at due to lazy token refresh, and explicitly states that token/client-secret material is never returned. This is exactly the kind of context an agent needs to use the response correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, then adds concise but important behavioral caveats. Every sentence earns its place, and the warning about expires_at is structured as actionable guidance rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the zero parameters, the readOnlyHint annotation, and the presence of an output schema, the description covers all relevant aspects an agent needs: what is returned, how to interpret ambiguous fields, and what is never returned. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema documents all of them (100% coverage), so there is no gap to compensate for. The baseline for a zero-parameter tool is 4, and the description has no need to add parameter-specific meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('List') and a precise resource ('the authenticated account's third-party OAuth connections'), and enumerates the returned fields. This clearly distinguishes it from sibling tools like list_agents or list_runs, even though no sibling is named.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The first sentence provides clear context for when to call the tool: when you need a read-only view of the account's OAuth connections. It does not explicitly contrast with alternatives, but the resource is unambiguous and no closely related sibling exists, so the usage context is clear without formal exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_pending_inputsList pending questionsARead-onlyInspect
List the agent's runs that are paused awaiting a human approval or input (the HITL queue). A row with a "consent_tool" is a write-consent approval: answering it with always_allow=true also stops the agent asking for that tool, and scope="thread" allows only the rest of this conversation's calls to the same connection, method and host. A request whose session has already moved on is not listed: a later run in that conversation has completed, so answering it would resume a superseded turn.
| Name | Required | Description | Default |
|---|---|---|---|
| agent_id | Yes | The agent's UUID. |
Output Schema
| Name | Required | Description |
|---|---|---|
| pending_inputs | Yes | Runs currently parked on a human approval or input request. A request whose session has already moved on is left out: answering it would resume a superseded turn. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description explains significant behaviors: it lists only paused runs, it includes consent_tool approval semantics with always_allow=true and scope='thread', and it explicitly notes that stale/superseded requests are omitted. This provides actionable detail that annotations alone do not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and information-dense, with the core purpose stated first and important behavioral caveats following. Every sentence adds meaningful value, and the length is appropriate for the complexity of the HITL semantics being explained.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the single parameter, the presence of an output schema, and the readOnlyHint annotation, the description covers the essential context for correct use: what is listed, what the consent_tool rows mean, and how stale requests are handled. No critical operational questions remain unanswered for an agent invoking this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, agent_id, is fully described in the schema as 'The agent's UUID.' The description adds minimal interpretive value beyond implying the tool lists runs for a given agent, so it meets the baseline for high schema coverage without adding much new semantic insight.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List') and a well-defined resource ('the agent's runs that are paused awaiting a human approval or input'), clearly identifying this as the HITL queue listing tool. This distinguishes it from related tools like answer_pending_input by focusing on listing pending items rather than resolving them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context about what the tool returns and even explains when requests are excluded (if the session has moved on). It does not explicitly name sibling alternatives or state 'use this instead of X', but the domain is straightforward enough that an agent can infer when listing pending inputs is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_runsList runsARead-onlyInspect
List an agent's run history, most recently STARTED first, with each run's status, timing and attributed cost. Returns the newest 20 runs unless you pass limit (maximum 100). When more history exists the result carries next_cursor; pass it back as cursor for the next page, and stop when it is absent. Each row's session_id (the same value as thread_id) continues that conversation through invoke_agent. tool_progress is null for a terminal run and for a run with no telemetry; a non-terminal row reports the same progress get_run_result does. A row with input_expired is parked on a question its session has already moved past — start a new run rather than answering it.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | How many runs to return, newest first (default 20, maximum 100). | |
| cursor | No | The next_cursor from a previous list_runs result, to continue where it stopped. Omit for the newest page. | |
| agent_id | Yes | The agent's UUID. |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | One page of the agent's runs, most recently started first. |
| next_cursor | No | Pass this back as cursor to read the next page. Absent when this page is the end of the history. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnly=true, but the description richly discloses additional behavior: newest-first ordering, default/maximum limit, cursor pagination, null tool_progress semantics, the session_id/thread_id equivalence, and input_expired handling. This goes well beyond what annotations convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficient and front-loaded with the core purpose. Each subsequent sentence covers a distinct operational concern such as pagination, session continuation, progress reporting, or terminal-state edge cases—no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and annotations covering read-only behavior, the description still supplies all practical details needed to use the tool correctly: ordering, limits, cursor flow, session continuation, null fields, and a caution about input_expired rows. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds meaningful context beyond the schema: the default page size, the instruction to pass next_cursor back as cursor, when to stop paginating, and the semantic meaning of row fields like session_id and input_expired. These details materially help an agent call the tool correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the resource ('an agent's run history'), the action ('List'), and the ordering ('most recently STARTED first'). It also distinguishes this from sibling list tools by specifying run-level details like status, timing, cost, and pagination.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear procedural guidance for pagination ('pass it back as cursor... stop when it is absent') and explains when to continue a session via invoke_agent. It references get_run_result for progress semantics but does not explicitly state when to prefer list_runs over that sibling, so it falls just short of full exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_workflow_executionsList workflow executionsARead-onlyInspect
List a workflow's recent executions, most recent first. Each record includes status, fault, billing, trigger source, timing, credits, and timestamps. fault explains why a non-succeeded execution ended. user means the workflow's own steps or limits. A platform fault is never billed. fault is null when the execution succeeded. billed is the billing flag.
| Name | Required | Description | Default |
|---|---|---|---|
| workflow_id | Yes | The workflow's UUID (from list_workflows or create_workflow). |
Output Schema
| Name | Required | Description |
|---|---|---|
| executions | Yes | Recent workflow executions, most recent first. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, and the description does not contradict this. It adds valuable behavioral context by explaining fault semantics (null on success, platform faults never billed) and the billed flag, which goes beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loads the core purpose, and then adds useful field semantics without unnecessary verbosity. It is well-structured and easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not explain return values. It covers key field meanings and ordering, which is sufficient for a simple list tool. Minor gaps like pagination limits are not addressed but are not critical here.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The sole parameter workflow_id is fully described in the schema with a clear source hint. The description adds no further parameter-specific meaning, so it stays at the baseline of 3 given the high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists a workflow's recent executions, most recent first. It specifies the resource (workflow executions) and the action (list). It does not explicitly differentiate from the sibling get_workflow_execution, but the purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives such as get_workflow_execution. It does not mention any conditions for choosing this over other listing or retrieval tools, leaving the agent to infer usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_workflowsList workflowsARead-onlyInspect
List the workflows owned by the authenticated account, with each one's status, trigger, current version, and the agent that holds it (agent_id). Each workflow belongs to one agent — the one that built it — and that agent is the only one that can edit or run it from a chat. Pass agent_id to list just that agent's workflows, or agent_id="none" for the unassigned ones (created here or in the web app with no agent).
| Name | Required | Description | Default |
|---|---|---|---|
| agent_id | No | Optional: a UUID of one of your agents to list only its workflows, or "none" for the unassigned ones. |
Output Schema
| Name | Required | Description |
|---|---|---|
| workflows | Yes | Workflows visible to the authenticated account and optional agent filter. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the description doesn't need to restate that. It adds valuable behavioral context: each workflow is bound to a single agent who is the only one that can edit or run it from chat, and explains the 'none' semantics. This goes beyond the schema and annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is reasonably concise and front-loads the primary purpose and return fields. The ownership explanation is valuable and not excessive. It could be trimmed slightly, but it is well-structured and every sentence contributes.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values are already covered. The description covers key aspects: what is listed, the ownership constraint, and parameter usage. It does not mention pagination or ordering, but for a list tool with an output schema, that is a minor gap. Overall, it is sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents agent_id. The description enriches the parameter by explaining the ownership model and the special 'none' case, giving an agent deeper understanding of the parameter's purpose beyond the raw schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the exact action ('list the workflows owned by the authenticated account') and enumerates the returned fields (status, trigger, current version, agent_id). It clearly distinguishes from sibling tools like list_runs and get_workflow by focusing on workflow ownership and listing behavior.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explains when to pass agent_id and the special 'none' value for unassigned workflows, and it mentions that each workflow belongs to one agent. It does not explicitly contrast with alternatives like get_workflow or list_workflow_executions, but the context is clear enough for an agent to decide when to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_workflowRun workflowADestructiveInspect
Run a workflow now — a real execution with real side effects, billed like any run (a flat per-execution fee plus model usage). Waits briefly and returns the execution: terminal if it finished, else status "running" to poll with get_workflow_execution. The workflow must already have steps.
| Name | Required | Description | Default |
|---|---|---|---|
| workflow_id | Yes | The workflow's UUID (from list_workflows or create_workflow). | |
| trigger_payload | No | Optional sample input to hand the trigger (useful for a webhook workflow: run it with a sample body). |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| error | No | Arbitrary JSON owned by the producing engine. |
| fault | Yes | Why a non-succeeded execution ended. User means the workflow's own steps or limits. A platform fault is never billed. This field is null when the execution succeeded. |
| steps | No | Arbitrary JSON owned by the producing engine. |
| billed | Yes | The billing flag. True only for a user-fault succeeded, failed, or timed-out execution. |
| status | Yes | |
| credits | Yes | |
| ended_at | Yes | |
| created_at | Yes | |
| started_at | Yes | |
| step_stats | No | Arbitrary JSON owned by the producing engine. |
| duration_ms | Yes | |
| workflow_id | Yes | |
| trigger_source | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds valuable context beyond the annotations: it discloses billing ('billed like any run...'), the wait-and-return behavior, and the terminal vs 'running' status distinction. It does not contradict the annotations (destructiveHint=true, readOnlyHint=false), and the added details meaningfully inform an agent of side effects and polling needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two dense sentences that front-load purpose and billing, then explain behavior and precondition. Every sentence earns its place; there is no fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, side effects, billing, wait behavior, polling alternative, and a precondition. With an output schema present and full schema coverage, nothing essential is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters (workflow_id and trigger_payload) are fully documented in the schema. The description does not add new parameter-level detail, but it does set a precondition ('must already have steps') that is a prerequisite rather than a parameter attribute. Baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific action ('Run a workflow now') and distinguishes it from a mere preview by emphasizing 'real execution with real side effects.' It also differentiates from polling via get_workflow_execution, making the tool's unique purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says to poll with get_workflow_execution if the execution is still running, and it states the prerequisite that the workflow must already have steps. However, it does not contrast with schedule_run or other run-related alternatives, so the 'when-not' guidance is incomplete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
schedule_runSchedule agent runADestructiveInspect
Schedule a ONE-SHOT deferred run of an agent: it will be invoked once, later, with the given prompt, billed like any run, and appears in list_runs when it fires. Provide either delay_seconds (relative) or fire_at (an RFC3339 timestamp). For a recurring schedule, use create_workflow with a cron trigger instead.
| Name | Required | Description | Default |
|---|---|---|---|
| prompt | Yes | The message to send the agent when the schedule fires. | |
| fire_at | No | Fire at this RFC3339 timestamp (mutually exclusive with delay_seconds). | |
| agent_id | Yes | The agent's UUID. | |
| session_id | No | Optional thread/session id to deliver the scheduled run into. | |
| delay_seconds | No | Fire this many seconds from now (mutually exclusive with fire_at). |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| kind | Yes | |
| prompt | Yes | |
| status | Yes | |
| fire_at | No | |
| agent_id | Yes | |
| attempts | Yes | |
| metadata | No | Arbitrary JSON owned by the producing engine. |
| thread_id | No | |
| created_at | Yes | |
| last_error | No | |
| last_fired_at | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses that the run is invoked once, later, billed like any run, and appears in list_runs when it fires. These side effects go beyond the annotations, though the destructiveHint=true annotation is not clarified; this is a minor gap, not a contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the tool's core purpose, and every sentence adds useful information: one-shot semantics, side effects, timing options, and the sibling alternative. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 100% schema coverage, an output schema, and annotations, the description covers the remaining operational context: what kind of run it schedules, how it is billed/visible, how to express the time, and when to use an alternative.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already describes all five parameters and their mutual exclusivity, so the description adds little parameter-specific meaning beyond reinforcing 'either delay_seconds or fire_at.' This is the appropriate baseline for a 100% schema-coverage tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Schedule a ONE-SHOT deferred run of an agent.' It also differentiates from recurring schedules by explicitly naming create_workflow with a cron trigger as the alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It tells the agent when to use this tool (one-shot deferred run) and when not to (recurring schedules: 'use create_workflow with a cron trigger instead'). It also clarifies the two timing options, delay_seconds or fire_at.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_workflow_agentSet workflow agentAIdempotentInspect
Assign one of your agents to a workflow. Use this after delete_agent reports paused workflows, or when run_workflow returns workflow_agentless. If base_version is omitted, this tool reads the workflow's current version before it assigns the agent. A supplied stale base_version is rejected with the current version.
| Name | Required | Description | Default |
|---|---|---|---|
| agent_id | Yes | The UUID of one of your agents to assign. | |
| workflow_id | Yes | The workflow's UUID. | |
| base_version | No | Optional workflow current_version to compare before assignment. Omit it to use the current version. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | A short confirmation of the assignment. |
| version | Yes | The workflow current_version checked for this assignment. |
| agent_id | Yes | The account-owned agent assigned to the workflow. |
| workflow_id | Yes | The workflow whose agent changed. |
| agent_deleted_at | Yes | Always null after assigning an agent: the workflow is no longer marked agentless. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description explains important behavior: when base_version is omitted, the tool reads the workflow's current version, and a stale base_version is rejected with the current version. This adds meaningful concurrency semantics not captured by readOnlyHint or idempotentHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences cover purpose, usage triggers, and the key concurrency nuance with no wasted words. The most actionable information is front-loaded in the first sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that annotations convey idempotency and non-destructiveness, and an output schema exists, the description adequately covers when to use the tool, how the version check behaves, and what to expect on stale versions. No critical information for a correct call is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds extra semantic value by explaining the stale base_version rejection behavior and clarifying what happens when base_version is omitted, which goes beyond the schema's brief parameter text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Assign one of your agents to a workflow.' It also provides concrete trigger scenarios, making the tool's purpose unmistakable and distinct from sibling operations like create_workflow or edit_workflow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage triggers: 'Use this after delete_agent reports paused workflows, or when run_workflow returns workflow_agentless.' It clearly indicates when to use the tool, though it does not mention when not to use it or suggest an alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
7 tool updates
v0.16.2- Changed
create_agent2 fields changed- added
Output schema / properties / advisor_max_spend_micro_usdAdded value: +{ + "description": "Optional maximum advisor-completion spend per turn in micro-US-dollars. Zero disables advisor completions; null leaves no spend cap.", + "type": [ + "null", + "integer" + ] +} - changed
Output schema / requiredPrevious value: -[ - "id", - "user_id", - "name", - "backend", - "model", - "effective_model", - "config", - "created_at" -]New value: +[ + "id", + "user_id", + "name", + "backend", + "model", + "advisor_max_spend_micro_usd", + "effective_model", + "config", + "created_at" +]
- Changed
get_agent2 fields changed- added
Output schema / properties / advisor_max_spend_micro_usdAdded value: +{ + "description": "Optional maximum advisor-completion spend per turn in micro-US-dollars. Zero disables advisor completions; null leaves no spend cap.", + "type": [ + "null", + "integer" + ] +} - changed
Output schema / requiredPrevious value: -[ - "id", - "user_id", - "name", - "backend", - "model", - "effective_model", - "config", - "created_at", - "mailbox" -]New value: +[ + "id", + "user_id", + "name", + "backend", + "model", + "advisor_max_spend_micro_usd", + "effective_model", + "config", + "created_at", + "mailbox" +]
- Changed
get_run_result3 fields changed- added
Output schema / properties / advisorAdded 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" +} - added
Output schema / properties / error / properties / upgradeAdded 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" + ] +} - added
Output schema / properties / usage_by_roleAdded 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" + ] +}
- Changed
get_usage11 fields changed- added
Output schema / properties / by_roleAdded value: +{ + "additionalProperties": false, + "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": "object" +} - added
Output schema / properties / recent_runs / items / properties / advisorAdded value: +{ + "additionalProperties": false, + "description": "Gross advisor consumption for the turn; the cap compares against this amount.", + "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" +} - added
Output schema / properties / recent_runs / items / properties / credits / descriptionAdded value: +"The net charge after any refund." - added
Output schema / properties / recent_runs / items / properties / error / properties / upgradeAdded 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" + ] +} - added
Output schema / properties / recent_runs / items / properties / gross_micro_usdAdded value: +{ + "description": "Gross consumption before any refund.", + "type": "integer" +} - added
Output schema / properties / recent_runs / items / properties / refund_reasonAdded value: +{ + "type": "string" +} - added
Output schema / properties / recent_runs / items / properties / refund_withheld_reasonAdded value: +{ + "type": "string" +} - added
Output schema / properties / recent_runs / items / properties / refunded_micro_usdAdded value: +{ + "description": "The refund reported once for this run.", + "type": "integer" +} - added
Output schema / properties / recent_runs / items / properties / usage_by_roleAdded value: +{ + "additionalProperties": false, + "description": "Gross consumption by role; credits sum to gross_micro_usd and refunds appear only in refunded_micro_usd.", + "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" + ] +} - changed
Output schema / properties / recent_runs / items / requiredPrevious value: -[ - "id", - "agent_id", - "thread_id", - "session_id", - "status", - "origin", - "started_at", - "credits", - "tokens", - "tool_progress" -]New value: +[ + "id", + "agent_id", + "thread_id", + "session_id", + "status", + "origin", + "started_at", + "credits", + "tokens", + "advisor", + "tool_progress" +] - changed
Output schema / requiredPrevious value: -[ - "totals", - "by_kind", - "tools", - "agents", - "workflows", - "workflow_executions", - "recent_runs" -]New value: +[ + "totals", + "by_role", + "by_kind", + "tools", + "agents", + "workflows", + "workflow_executions", + "recent_runs" +]
- Changed
invoke_agent4 fields changed- added
Input schema / properties / max_advisor_spend_micro_usdAdded value: +{ + "description": "Optional maximum advisor-completion spend for this turn in micro-US-dollars. 0 disables advisor completions. Omit it to use the agent setting; when neither is set, at most two advisor calls can run. The maximum is 5,000,000.", + "maximum": 5000000, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / advisorAdded 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" +} - added
Output schema / properties / error / properties / upgradeAdded 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" + ] +} - added
Output schema / properties / usage_by_roleAdded 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" + ] +}
- Changed
list_agents2 fields changed- added
Output schema / properties / items / items / properties / advisor_max_spend_micro_usdAdded value: +{ + "description": "Optional maximum advisor-completion spend per turn in micro-US-dollars. Zero disables advisor completions; null leaves no spend cap.", + "type": [ + "null", + "integer" + ] +} - changed
Output schema / properties / items / items / requiredPrevious value: -[ - "id", - "user_id", - "name", - "backend", - "model", - "effective_model", - "config", - "created_at" -]New value: +[ + "id", + "user_id", + "name", + "backend", + "model", + "advisor_max_spend_micro_usd", + "effective_model", + "config", + "created_at" +]
- Changed
list_runs9 fields changed- added
Output schema / properties / items / items / properties / advisorAdded value: +{ + "additionalProperties": false, + "description": "Gross advisor consumption for the turn; the cap compares against this amount.", + "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" +} - added
Output schema / properties / items / items / properties / credits / descriptionAdded value: +"The net charge after any refund." - added
Output schema / properties / items / items / properties / error / properties / upgradeAdded 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" + ] +} - added
Output schema / properties / items / items / properties / gross_micro_usdAdded value: +{ + "description": "Gross consumption before any refund.", + "type": "integer" +} - added
Output schema / properties / items / items / properties / refund_reasonAdded value: +{ + "type": "string" +} - added
Output schema / properties / items / items / properties / refund_withheld_reasonAdded value: +{ + "type": "string" +} - added
Output schema / properties / items / items / properties / refunded_micro_usdAdded value: +{ + "description": "The refund reported once for this run.", + "type": "integer" +} - added
Output schema / properties / items / items / properties / usage_by_roleAdded value: +{ + "additionalProperties": false, + "description": "Gross consumption by role; credits sum to gross_micro_usd and refunds appear only in refunded_micro_usd.", + "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" + ] +} - changed
Output schema / properties / items / items / requiredPrevious value: -[ - "id", - "agent_id", - "thread_id", - "session_id", - "status", - "origin", - "started_at", - "credits", - "tokens", - "tool_progress" -]New value: +[ + "id", + "agent_id", + "thread_id", + "session_id", + "status", + "origin", + "started_at", + "credits", + "tokens", + "advisor", + "tool_progress" +]
26 tool updates
v0.16.0- Changed
answer_pending_input2 fields changed- added
Input schema / properties / scopeAdded value: +{ + "description": "Set to \"thread\" to approve AND allow the rest of this conversation's writes to the same connection, method and host, instead of a standing grant. It expires after 24 hours and covers no other host, method or conversation. Only set it when the human said to stop being asked for the rest of this task; ignored without approved=true, and on a card that has no such scope. Cannot be combined with always_allow.", + "type": "string" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "already": { + "description": "Whether this request had already been answered.", + "type": "boolean" + }, + "run_id": { + "description": "The continuation run created by the answer.", + "type": "string" + }, + "session_id": { + "description": "The continuation run's session.", + "type": "string" + }, + "status": { + "description": "Answer status.", + "type": "string" + }, + "tool_call_id": { + "description": "The pending tool call that was answered.", + "type": "string" + } + }, + "required": [ + "status", + "tool_call_id" + ], + "type": "object" +}
- Changed
cancel_run1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "runId": { + "description": "The run whose cancellation was requested.", + "type": "string" + }, + "status": { + "description": "Cancellation request status.", + "type": "string" + } + }, + "required": [ + "runId", + "status" + ], + "type": "object" +}
- Changed
create_agent2 fields changed- removed
Input schema / properties / modelRemoved value: -{ - "description": "Optional model slug; omitted uses the Plori Router, which picks the cheapest model that fits each task from the pool the account's plan unlocks. An explicit frontier model still requires a paid plan.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "backend": { + "description": "The compute backend this Agent runs on.", + "type": "string" + }, + "config": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "created_at": { + "description": "When the Agent was created.", + "type": "string" + }, + "deleting": { + "description": "True while this Agent's disk is still being erased; offer no action on it besides retrying the deletion itself.", + "type": "boolean" + }, + "deleting_since": { + "description": "When the deletion was first requested; present only while deleting is true.", + "type": [ + "null", + "string" + ] + }, + "effective_model": { + "description": "The model a run on this Agent will actually use. plori-auto means the hosted router chooses per turn.", + "type": "string" + }, + "existing": { + "description": "Whether create_agent returned an existing same-name agent instead of creating one.", + "type": "boolean" + }, + "id": { + "description": "The Agent's unique identifier; pass it to other tools as agent_id.", + "type": "string" + }, + "last_run_at": { + "description": "When this Agent last started a run; absent when it has never run.", + "type": [ + "null", + "string" + ] + }, + "model": { + "description": "The model slug this Agent is configured to use. Empty means no explicit choice, which is not the same as no model — read effective_model for what a run will actually use.", + "type": "string" + }, + "moving": { + "description": "True while this Agent's files are being copied to a new disk; check storage_notice rather than a separate route for the outcome.", + "type": "boolean" + }, + "name": { + "description": "The Agent's name, chosen by its owner and unique within the account.", + "type": "string" + }, + "queued_at": { + "description": "When a still-warming attach was accepted; present only while it is queued for node capacity.", + "type": [ + "null", + "string" + ] + }, + "status": { + "description": "The live warm-session state: warming, ready, or sleeping; empty when no session is active.", + "type": "string" + }, + "storage_notice": { + "description": "The one sentence, if any, telling the owner about a storage move that stopped; show it verbatim, not paraphrased.", + "type": "string" + }, + "url": { + "description": "This Agent's page in the plori web app.", + "type": "string" + }, + "user_id": { + "description": "The identifier of the account that owns this Agent.", + "type": "string" + } + }, + "required": [ + "id", + "user_id", + "name", + "backend", + "model", + "effective_model", + "config", + "created_at" + ], + "type": "object" +}
- Changed
create_workflow4 fields changed- changed
Input schema / properties / cron_expr / descriptionPrevious value: -"Cron schedule (required when trigger_kind is \"cron\"), e.g. \"0 9 * * *\"."New value: +"Cron schedule (required when trigger_kind is \"cron\"), e.g. \"0 9 * * *\". A 5-field cron or an @daily/@hourly descriptor, evaluated in UTC." - changed
Input schema / properties / description / descriptionPrevious value: -"Optional description of what the workflow does."New value: +"Optional description of what the workflow does. It is prose for the reader; no field is derived from it." - changed
Input schema / properties / trigger_kind / descriptionPrevious value: -"Optional trigger: \"manual\" (default), \"cron\", or \"webhook\"."New value: +"Optional trigger: \"manual\" (default), \"cron\", or \"webhook\". The build can change it later: a schedule or webhook trigger step sets it." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "active_version": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": [ + "null", + "integer" + ] + }, + "agent_deleted_at": { + "type": [ + "null", + "string" + ] + }, + "agent_id": { + "type": [ + "null", + "string" + ] + }, + "created_at": { + "type": "string" + }, + "cron_expr": { + "type": "string" + }, + "current_version": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "description": { + "type": "string" + }, + "engine": { + "type": "string" + }, + "hook_key": { + "type": [ + "null", + "string" + ] + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "next_fire_at": { + "type": [ + "null", + "string" + ] + }, + "notify_pref": { + "type": "string" + }, + "paused_reason": { + "type": "string" + }, + "spend_cap_month": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "template_slug": { + "type": "string" + }, + "trigger_kind": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "type": "string" + } + }, + "required": [ + "id", + "user_id", + "agent_id", + "name", + "description", + "engine", + "status", + "current_version", + "active_version", + "trigger_kind", + "cron_expr", + "next_fire_at", + "hook_key", + "spend_cap_month", + "notify_pref", + "created_at", + "updated_at" + ], + "type": "object" +}
- Changed
delete_agent1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "status": { + "description": "The successful HTTP status code from the underlying operation.", + "type": "integer" + }, + "workflows_paused": { + "description": "How many workflows this agent had built and had running were paused by the deletion. They are not deleted: assign them to another agent to run them again.", + "type": "integer" + } + }, + "required": [ + "status" + ], + "type": "object" +}
- Changed
edit_workflow1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "projection": { + "description": "The value-light projection of the edited workflow definition." + }, + "resolved": { + "description": "External identifiers resolved while binding the edit.", + "items": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "note": { + "type": "string" + }, + "prop": { + "type": "string" + }, + "step": { + "type": "string" + }, + "title": { + "type": "string" + } + }, + "required": [ + "step", + "prop", + "id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "version": { + "description": "The new draft version created by the edit.", + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "workflow_id": { + "description": "The edited workflow.", + "type": "string" + } + }, + "required": [ + "workflow_id", + "version", + "projection" + ], + "type": "object" +}
- Added
empty_trash - Changed
get_agent1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "backend": { + "description": "The compute backend this Agent runs on.", + "type": "string" + }, + "config": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "created_at": { + "description": "When the Agent was created.", + "type": "string" + }, + "deleting": { + "description": "True while this Agent's disk is still being erased; offer no action on it besides retrying the deletion itself.", + "type": "boolean" + }, + "deleting_since": { + "description": "When the deletion was first requested; present only while deleting is true.", + "type": [ + "null", + "string" + ] + }, + "effective_model": { + "description": "The model a run on this Agent will actually use. plori-auto means the hosted router chooses per turn.", + "type": "string" + }, + "id": { + "description": "The Agent's unique identifier; pass it to other tools as agent_id.", + "type": "string" + }, + "last_run_at": { + "description": "When this Agent last started a run; absent when it has never run.", + "type": [ + "null", + "string" + ] + }, + "mailbox": { + "description": "This agent's mailbox letters, open ones (accepted, delivering, blocked) first, then applied or undeliverable ones, newest within each group, at most 20.", + "items": { + "additionalProperties": false, + "properties": { + "accepted_at": { + "type": "string" + }, + "block_reason": { + "type": "string" + }, + "consumed_at": { + "type": [ + "null", + "string" + ] + }, + "correlation_id": { + "type": "string" + }, + "from_agent": { + "type": "string" + }, + "id": { + "type": "string" + }, + "in_reply_to": { + "type": [ + "null", + "string" + ] + }, + "kind": { + "type": "string" + }, + "run_id": { + "type": [ + "null", + "string" + ] + }, + "status": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "to_agent": { + "type": "string" + } + }, + "required": [ + "id", + "kind", + "from_agent", + "to_agent", + "status", + "in_reply_to", + "correlation_id", + "run_id", + "summary", + "accepted_at", + "consumed_at" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "model": { + "description": "The model slug this Agent is configured to use. Empty means no explicit choice, which is not the same as no model — read effective_model for what a run will actually use.", + "type": "string" + }, + "moving": { + "description": "True while this Agent's files are being copied to a new disk; check storage_notice rather than a separate route for the outcome.", + "type": "boolean" + }, + "name": { + "description": "The Agent's name, chosen by its owner and unique within the account.", + "type": "string" + }, + "queued_at": { + "description": "When a still-warming attach was accepted; present only while it is queued for node capacity.", + "type": [ + "null", + "string" + ] + }, + "status": { + "description": "The live warm-session state: warming, ready, or sleeping; empty when no session is active.", + "type": "string" + }, + "storage_notice": { + "description": "The one sentence, if any, telling the owner about a storage move that stopped; show it verbatim, not paraphrased.", + "type": "string" + }, + "url": { + "description": "This Agent's page in the plori web app.", + "type": "string" + }, + "user_id": { + "description": "The identifier of the account that owns this Agent.", + "type": "string" + } + }, + "required": [ + "id", + "user_id", + "name", + "backend", + "model", + "effective_model", + "config", + "created_at", + "mailbox" + ], + "type": "object" +}
- Changed
get_credits1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "account_email": { + "description": "The email address of the account this balance belongs to.", + "type": "string" + }, + "active_plan": { + "additionalProperties": false, + "description": "The account's current subscription, or null when it has none and is on the free tier.", + "properties": { + "cancel_at_period_end": { + "type": "boolean" + }, + "current_period_end": { + "type": [ + "null", + "string" + ] + }, + "monthly_credits": { + "description": "Credits this plan adds each month, in the same credits as balance.", + "type": "integer" + }, + "sku": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "sku", + "monthly_credits", + "status", + "current_period_end", + "cancel_at_period_end" + ], + "type": [ + "null", + "object" + ] + }, + "audience": { + "type": "string" + }, + "balance": { + "description": "The account's remaining prepaid balance, in credits. 1,000,000 credits = 1 US dollar.", + "type": "integer" + }, + "balance_usd": { + "description": "The account balance formatted in US dollars, without a currency symbol.", + "type": "string" + }, + "can_manage_billing": { + "type": "boolean" + }, + "limits": { + "additionalProperties": false, + "description": "The caps this account's plan tier enforces.", + "properties": { + "max_active_workflows": { + "description": "How many active workflows this plan tier may have. 0 means unlimited. An anonymous trial cannot activate a workflow at all.", + "type": "integer" + }, + "max_agents": { + "description": "How many agents this plan tier may own. 0 means unlimited. An anonymous trial is capped at one agent whatever this says.", + "type": "integer" + }, + "max_concurrent_runs": { + "description": "How many agent runs this plan tier may have in flight at once. 0 means unlimited.", + "type": "integer" + } + }, + "required": [ + "max_agents", + "max_concurrent_runs", + "max_active_workflows" + ], + "type": "object" + }, + "low_credit_threshold": { + "description": "The balance, in the same credits, below which this account is warned it is running low.", + "type": "integer" + }, + "packs": { + "description": "Credit packs this account can buy. Each pack's usd_cents is its price in US cents and its credits are what the purchase adds to balance.", + "items": { + "additionalProperties": false, + "properties": { + "credits": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "usd_cents": { + "type": "integer" + } + }, + "required": [ + "id", + "usd_cents", + "credits" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "plan_tier": { + "description": "The plan tier this account resolves to: free, pro or power. An account with no active plan is free.", + "type": "string" + }, + "plans": { + "description": "Subscription plans on offer, with their monthly credit grant.", + "items": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "monthly_credits": { + "type": "integer" + }, + "usd_cents": { + "type": "integer" + } + }, + "required": [ + "id", + "usd_cents", + "monthly_credits" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "user_id": { + "description": "The identifier of the account this balance belongs to.", + "type": "string" + } + }, + "required": [ + "balance", + "low_credit_threshold", + "packs", + "plans", + "active_plan", + "can_manage_billing", + "audience", + "user_id", + "account_email", + "plan_tier", + "limits", + "balance_usd" + ], + "type": "object" +}
- Changed
get_disk1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "included_bytes": { + "type": "integer" + }, + "monthly_credits": { + "type": "integer" + }, + "purchased_bytes": { + "type": "integer" + }, + "storage_credits_per_gb": { + "type": "integer" + }, + "total_bytes": { + "type": "integer" + }, + "trash_bytes": { + "type": [ + "null", + "integer" + ] + }, + "usage_observed_at": { + "description": "When a mount last reported the used figure. Present only while a mount is holding one of the account's disks; when none is, nothing can be changing the figure and there is no reporting clock to quote.", + "type": [ + "null", + "string" + ] + }, + "usage_stale": { + "description": "True when a mount is holding one of the account's disks but has not reported its usage within the writer-lease lifetime. used_bytes is then the last figure that mount reported, not the current one — treat it as a floor and say so rather than quoting it as the account's usage.", + "type": "boolean" + }, + "used_bytes": { + "type": "integer" + }, + "warning_level": { + "type": "integer" + } + }, + "required": [ + "included_bytes", + "purchased_bytes", + "total_bytes", + "used_bytes", + "warning_level", + "storage_credits_per_gb", + "monthly_credits" + ], + "type": "object" +}
- Changed
get_run_result3 fields changed- added
Input schema / properties / waitAdded 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" +} - added
Input schema / properties / wait_secondsAdded 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" +} - changed
Output 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" +}
- Changed
get_usage1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "agents": { + "items": { + "additionalProperties": false, + "properties": { + "agent_id": { + "type": "string" + }, + "backend": { + "type": "string" + }, + "breakdown": { + "items": { + "additionalProperties": false, + "properties": { + "credits": { + "type": "integer" + }, + "events": { + "type": "integer" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "tokens": { + "type": "integer" + } + }, + "required": [ + "kind", + "events", + "tokens", + "credits" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "credits": { + "type": "integer" + }, + "events": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tokens": { + "type": "integer" + } + }, + "required": [ + "agent_id", + "name", + "backend", + "credits", + "tokens", + "events" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "by_kind": { + "items": { + "additionalProperties": false, + "properties": { + "credits": { + "type": "integer" + }, + "events": { + "type": "integer" + }, + "kind": { + "type": "string" + }, + "tokens": { + "type": "integer" + } + }, + "required": [ + "kind", + "credits", + "tokens", + "events" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "recent_runs": { + "items": { + "additionalProperties": false, + "properties": { + "agent_id": { + "description": "The agent that ran it.", + "type": "string" + }, + "cause": { + "type": "string" + }, + "command_error": { + "type": "string" + }, + "command_state": { + "type": "string" + }, + "continuation_run_id": { + "type": "string" + }, + "credits": { + "type": [ + "null", + "integer" + ] + }, + "ended_at": { + "type": [ + "null", + "string" + ] + }, + "error": { + "additionalProperties": false, + "description": "Why a terminal error or cancelled run failed, 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" + ] + }, + "id": { + "description": "The run's public identifier; pass it to get_run_result as run_id.", + "type": "string" + }, + "input_expired": { + "description": "True when this run is parked on a question its session has moved past: a later run in the same conversation has completed, so answering it would resume a superseded turn. Do not answer it; start a new run instead.", + "type": "boolean" + }, + "input_status": { + "type": "string" + }, + "input_updated_at": { + "type": [ + "null", + "string" + ] + }, + "last_heartbeat_at": { + "type": [ + "null", + "string" + ] + }, + "origin": { + "description": "What started this run: user, schedule, email, background, agent or agent_result.", + "type": "string" + }, + "parent_run_id": { + "type": "string" + }, + "resume_run_id": { + "type": "string" + }, + "resume_status": { + "type": "string" + }, + "retryable": { + "type": "boolean" + }, + "session_id": { + "description": "The conversation this run belongs to; pass it to invoke_agent as session_id to continue it. Identical to thread_id.", + "type": "string" + }, + "started_at": { + "type": "string" + }, + "status": { + "description": "The run's status: queued, running, awaiting_input, completed, error or cancelled.", + "type": "string" + }, + "stop_reason": { + "type": "string" + }, + "thread_id": { + "description": "The conversation this run belongs to. Identical to session_id.", + "type": "string" + }, + "tokens": { + "type": [ + "null", + "integer" + ] + }, + "tool_progress": { + "additionalProperties": false, + "description": "Durable tool execution progress, from the same telemetry get_run_result reads. Null for a run with no telemetry, and for a terminal run, which has no call in flight to report.", + "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" + } + }, + "required": [ + "id", + "agent_id", + "thread_id", + "session_id", + "status", + "origin", + "started_at", + "credits", + "tokens", + "tool_progress" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "tools": { + "items": { + "additionalProperties": false, + "properties": { + "calls": { + "type": "integer" + }, + "credits": { + "type": "integer" + }, + "free_calls": { + "type": "integer" + }, + "tool": { + "type": "string" + } + }, + "required": [ + "tool", + "calls", + "free_calls", + "credits" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "totals": { + "additionalProperties": false, + "properties": { + "credits": { + "type": "integer" + }, + "runs": { + "type": "integer" + }, + "tokens": { + "type": "integer" + } + }, + "required": [ + "credits", + "tokens", + "runs" + ], + "type": "object" + }, + "workflow_executions": { + "items": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "credits": { + "type": "integer" + }, + "duration_ms": { + "type": "integer" + }, + "ended_at": { + "type": [ + "null", + "string" + ] + }, + "fault": { + "type": "string" + }, + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "trigger_source": { + "type": "string" + }, + "workflow_id": { + "type": "string" + }, + "workflow_name": { + "type": "string" + } + }, + "required": [ + "id", + "workflow_id", + "workflow_name", + "status", + "trigger_source", + "duration_ms", + "credits", + "created_at" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "workflows": { + "items": { + "additionalProperties": false, + "properties": { + "billed_runs": { + "type": "integer" + }, + "credits": { + "type": "integer" + }, + "exec_credits": { + "type": "integer" + }, + "model_credits": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tokens": { + "type": "integer" + }, + "workflow_id": { + "type": "string" + } + }, + "required": [ + "workflow_id", + "name", + "billed_runs", + "exec_credits", + "model_credits", + "credits", + "tokens" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + } + }, + "required": [ + "totals", + "by_kind", + "tools", + "agents", + "workflows", + "workflow_executions", + "recent_runs" + ], + "type": "object" +}
- Changed
get_workflow1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "active_version": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": [ + "null", + "integer" + ] + }, + "agent_deleted_at": { + "type": [ + "null", + "string" + ] + }, + "agent_id": { + "type": [ + "null", + "string" + ] + }, + "created_at": { + "type": "string" + }, + "cron_expr": { + "type": "string" + }, + "current_version": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "description": { + "type": "string" + }, + "engine": { + "type": "string" + }, + "hook_key": { + "type": [ + "null", + "string" + ] + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "next_fire_at": { + "type": [ + "null", + "string" + ] + }, + "notify_pref": { + "type": "string" + }, + "paused_reason": { + "type": "string" + }, + "projection": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "spend_cap_month": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "template_slug": { + "type": "string" + }, + "trigger_kind": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "type": "string" + } + }, + "required": [ + "id", + "user_id", + "agent_id", + "name", + "description", + "engine", + "status", + "current_version", + "active_version", + "trigger_kind", + "cron_expr", + "next_fire_at", + "hook_key", + "spend_cap_month", + "notify_pref", + "created_at", + "updated_at", + "projection" + ], + "type": "object" +}
- Changed
get_workflow_execution1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "billed": { + "description": "The billing flag. True only for a user-fault succeeded, failed, or timed-out execution.", + "type": "boolean" + }, + "created_at": { + "type": "string" + }, + "credits": { + "type": [ + "null", + "integer" + ] + }, + "duration_ms": { + "type": [ + "null", + "integer" + ] + }, + "ended_at": { + "type": [ + "null", + "string" + ] + }, + "error": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "fault": { + "description": "Why a non-succeeded execution ended. User means the workflow's own steps or limits. A platform fault is never billed. This field is null when the execution succeeded.", + "type": [ + "null", + "string" + ] + }, + "id": { + "type": "string" + }, + "started_at": { + "type": [ + "null", + "string" + ] + }, + "status": { + "type": "string" + }, + "step_stats": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "steps": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "trigger_source": { + "type": "string" + }, + "workflow_id": { + "type": "string" + } + }, + "required": [ + "id", + "workflow_id", + "status", + "fault", + "billed", + "trigger_source", + "started_at", + "ended_at", + "duration_ms", + "credits", + "created_at" + ], + "type": "object" +}
- Changed
get_workflow_version1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "author": { + "type": "string" + }, + "chat_run_id": { + "type": [ + "null", + "string" + ] + }, + "created_at": { + "type": "string" + }, + "definition": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "id": { + "type": "string" + }, + "projection": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "version": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "workflow_id": { + "type": "string" + } + }, + "required": [ + "id", + "workflow_id", + "version", + "author", + "chat_run_id", + "created_at" + ], + "type": "object" +}
- Changed
invoke_agent7 fields changed- added
Input schema / properties / callback_secretAdded value: +{ + "description": "Optional secret used to sign callback deliveries with HMAC-SHA256.", + "type": "string" +} - added
Input schema / properties / callback_urlAdded value: +{ + "description": "Optional callback URL for this run. Must use http or https and resolve only to public addresses.", + "type": "string" +} - changed
Input schema / properties / max_turn_seconds / descriptionPrevious value: -"Optional soft wall-clock budget for this turn in seconds (0 or omitted uses forge's deployment default; maximum 14,400). It schedules an in-loop checkpoint and does not cancel the run."New value: +"Optional soft wall-clock budget for this turn in seconds, maximum 14,400. 0 or omitted uses the deployment's configured default, and where none is configured a turn has no wall-clock budget at all. It schedules an in-loop checkpoint and does not cancel the run." - changed
Input schema / properties / max_turn_tokens / descriptionPrevious value: -"Optional cumulative cache-weighted token ceiling for this turn (0 or omitted uses forge's default; maximum 5,000,000). The agent reserves its final 2% for a tool-free wrap-up."New value: +"Optional cumulative cache-weighted token ceiling for this turn. 0 or omitted uses the agent's default of 2,000,000; the maximum is 5,000,000. The agent reserves its final 2% for a tool-free wrap-up." - changed
Input schema / properties / wait / descriptionPrevious value: -"Wait (up to ~25s) for the turn and return the reply (default true). Set false to return a run_id immediately and poll get_run_result — prefer this for long or tool-heavy turns so the call doesn't block your own turn."New value: +"Wait for the turn and return the reply (default true); the hold lasts as long as your client keeps the call open, or wait_seconds. Set false to return a run_id immediately and poll get_run_result — prefer this for long or tool-heavy turns so the call doesn't block your own turn." - added
Input schema / properties / wait_secondsAdded value: +{ + "description": "Optional: how many seconds to wait for the turn before returning a \"running\" run_id (maximum 1800). Omit to use the window your MCP client can hold. Ignored when wait=false.", + "maximum": 1800, + "minimum": 0, + "type": "integer" +} - changed
Output 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" +}
- Changed
list_agents1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "items": { + "description": "The returned items, in the endpoint's documented order.", + "items": { + "additionalProperties": false, + "properties": { + "backend": { + "description": "The compute backend this Agent runs on.", + "type": "string" + }, + "config": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "created_at": { + "description": "When the Agent was created.", + "type": "string" + }, + "deleting": { + "description": "True while this Agent's disk is still being erased; offer no action on it besides retrying the deletion itself.", + "type": "boolean" + }, + "deleting_since": { + "description": "When the deletion was first requested; present only while deleting is true.", + "type": [ + "null", + "string" + ] + }, + "effective_model": { + "description": "The model a run on this Agent will actually use. plori-auto means the hosted router chooses per turn.", + "type": "string" + }, + "id": { + "description": "The Agent's unique identifier; pass it to other tools as agent_id.", + "type": "string" + }, + "last_run_at": { + "description": "When this Agent last started a run; absent when it has never run.", + "type": [ + "null", + "string" + ] + }, + "model": { + "description": "The model slug this Agent is configured to use. Empty means no explicit choice, which is not the same as no model — read effective_model for what a run will actually use.", + "type": "string" + }, + "moving": { + "description": "True while this Agent's files are being copied to a new disk; check storage_notice rather than a separate route for the outcome.", + "type": "boolean" + }, + "name": { + "description": "The Agent's name, chosen by its owner and unique within the account.", + "type": "string" + }, + "queued_at": { + "description": "When a still-warming attach was accepted; present only while it is queued for node capacity.", + "type": [ + "null", + "string" + ] + }, + "status": { + "description": "The live warm-session state: warming, ready, or sleeping; empty when no session is active.", + "type": "string" + }, + "storage_notice": { + "description": "The one sentence, if any, telling the owner about a storage move that stopped; show it verbatim, not paraphrased.", + "type": "string" + }, + "url": { + "description": "This Agent's page in the plori web app.", + "type": "string" + }, + "user_id": { + "description": "The identifier of the account that owns this Agent.", + "type": "string" + } + }, + "required": [ + "id", + "user_id", + "name", + "backend", + "model", + "effective_model", + "config", + "created_at" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + } + }, + "required": [ + "items" + ], + "type": "object" +}
- Changed
list_connections1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "connections": { + "description": "Third-party OAuth connection status records; never secret material.", + "items": { + "additionalProperties": false, + "properties": { + "authorized_at": { + "description": "When the grant was last authorized; null when there has never been one.", + "type": [ + "null", + "string" + ] + }, + "expires_at": { + "description": "When the current access token expires; null when the grant does not expire. A past value on an authorized row is normal — tokens refresh lazily when used.", + "type": [ + "null", + "string" + ] + }, + "needs_reauth": { + "description": "True when a human must reconnect this provider before it can be used. Read this rather than comparing expires_at to the clock.", + "type": "boolean" + }, + "provider": { + "description": "The third-party provider this row is about.", + "type": "string" + }, + "scopes": { + "description": "The scopes this provider is configured to request.", + "items": { + "type": "string" + }, + "type": [ + "null", + "array" + ] + }, + "status": { + "description": "authorized, reconnect_needed, or unauthorized.", + "type": "string" + } + }, + "required": [ + "provider", + "status", + "authorized_at", + "expires_at", + "scopes", + "needs_reauth" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + } + }, + "required": [ + "connections" + ], + "type": "object" +}
- Changed
list_pending_inputs1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "pending_inputs": { + "description": "Runs currently parked on a human approval or input request. A request whose session has already moved on is left out: answering it would resume a superseded turn.", + "items": { + "additionalProperties": false, + "properties": { + "agent_id": { + "type": "string" + }, + "args": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "connect": { + "additionalProperties": false, + "properties": { + "provider": { + "type": "string" + }, + "workflow_id": { + "type": "string" + } + }, + "required": [ + "workflow_id", + "provider" + ], + "type": [ + "null", + "object" + ] + }, + "consent_tool": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "expires_at": { + "type": [ + "null", + "string" + ] + }, + "id": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "prompt": { + "type": "string" + }, + "risk": { + "type": "string" + }, + "run_id": { + "type": "string" + }, + "schema": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "secret": { + "type": "boolean" + }, + "status": { + "type": "string" + }, + "tool_call_id": { + "type": "string" + } + }, + "required": [ + "id", + "run_id", + "agent_id", + "tool_call_id", + "kind", + "prompt", + "status", + "created_at" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + } + }, + "required": [ + "pending_inputs" + ], + "type": "object" +}
- Changed
list_runs3 fields changed- added
Input schema / properties / cursorAdded value: +{ + "description": "The next_cursor from a previous list_runs result, to continue where it stopped. Omit for the newest page.", + "type": "string" +} - added
Input schema / properties / limitAdded value: +{ + "description": "How many runs to return, newest first (default 20, maximum 100).", + "maximum": 100, + "minimum": 1, + "type": "integer" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "items": { + "description": "One page of the agent's runs, most recently started first.", + "items": { + "additionalProperties": false, + "properties": { + "agent_id": { + "description": "The agent that ran it.", + "type": "string" + }, + "cause": { + "type": "string" + }, + "command_error": { + "type": "string" + }, + "command_state": { + "type": "string" + }, + "continuation_run_id": { + "type": "string" + }, + "credits": { + "type": [ + "null", + "integer" + ] + }, + "ended_at": { + "type": [ + "null", + "string" + ] + }, + "error": { + "additionalProperties": false, + "description": "Why a terminal error or cancelled run failed, 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" + ] + }, + "id": { + "description": "The run's public identifier; pass it to get_run_result as run_id.", + "type": "string" + }, + "input_expired": { + "description": "True when this run is parked on a question its session has moved past: a later run in the same conversation has completed, so answering it would resume a superseded turn. Do not answer it; start a new run instead.", + "type": "boolean" + }, + "input_status": { + "type": "string" + }, + "input_updated_at": { + "type": [ + "null", + "string" + ] + }, + "last_heartbeat_at": { + "type": [ + "null", + "string" + ] + }, + "origin": { + "description": "What started this run: user, schedule, email, background, agent or agent_result.", + "type": "string" + }, + "parent_run_id": { + "type": "string" + }, + "resume_run_id": { + "type": "string" + }, + "resume_status": { + "type": "string" + }, + "retryable": { + "type": "boolean" + }, + "session_id": { + "description": "The conversation this run belongs to; pass it to invoke_agent as session_id to continue it. Identical to thread_id.", + "type": "string" + }, + "started_at": { + "type": "string" + }, + "status": { + "description": "The run's status: queued, running, awaiting_input, completed, error or cancelled.", + "type": "string" + }, + "stop_reason": { + "type": "string" + }, + "thread_id": { + "description": "The conversation this run belongs to. Identical to session_id.", + "type": "string" + }, + "tokens": { + "type": [ + "null", + "integer" + ] + }, + "tool_progress": { + "additionalProperties": false, + "description": "Durable tool execution progress, from the same telemetry get_run_result reads. Null for a run with no telemetry, and for a terminal run, which has no call in flight to report.", + "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" + } + }, + "required": [ + "id", + "agent_id", + "thread_id", + "session_id", + "status", + "origin", + "started_at", + "credits", + "tokens", + "tool_progress" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "next_cursor": { + "description": "Pass this back as cursor to read the next page. Absent when this page is the end of the history.", + "type": "string" + } + }, + "required": [ + "items" + ], + "type": "object" +}
- Changed
list_workflow_executions1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "executions": { + "description": "Recent workflow executions, most recent first.", + "items": { + "additionalProperties": false, + "properties": { + "billed": { + "description": "The billing flag. True only for a user-fault succeeded, failed, or timed-out execution.", + "type": "boolean" + }, + "created_at": { + "type": "string" + }, + "credits": { + "type": [ + "null", + "integer" + ] + }, + "duration_ms": { + "type": [ + "null", + "integer" + ] + }, + "ended_at": { + "type": [ + "null", + "string" + ] + }, + "error": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "fault": { + "description": "Why a non-succeeded execution ended. User means the workflow's own steps or limits. A platform fault is never billed. This field is null when the execution succeeded.", + "type": [ + "null", + "string" + ] + }, + "id": { + "type": "string" + }, + "started_at": { + "type": [ + "null", + "string" + ] + }, + "status": { + "type": "string" + }, + "step_stats": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "steps": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "trigger_source": { + "type": "string" + }, + "workflow_id": { + "type": "string" + } + }, + "required": [ + "id", + "workflow_id", + "status", + "fault", + "billed", + "trigger_source", + "started_at", + "ended_at", + "duration_ms", + "credits", + "created_at" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + } + }, + "required": [ + "executions" + ], + "type": "object" +}
- Changed
list_workflows1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "workflows": { + "description": "Workflows visible to the authenticated account and optional agent filter.", + "items": { + "additionalProperties": false, + "properties": { + "active_version": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": [ + "null", + "integer" + ] + }, + "agent_deleted_at": { + "type": [ + "null", + "string" + ] + }, + "agent_id": { + "type": [ + "null", + "string" + ] + }, + "created_at": { + "type": "string" + }, + "cron_expr": { + "type": "string" + }, + "current_version": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "description": { + "type": "string" + }, + "engine": { + "type": "string" + }, + "hook_key": { + "type": [ + "null", + "string" + ] + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "next_fire_at": { + "type": [ + "null", + "string" + ] + }, + "notify_pref": { + "type": "string" + }, + "paused_reason": { + "type": "string" + }, + "spend_cap_month": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "template_slug": { + "type": "string" + }, + "trigger_kind": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "type": "string" + } + }, + "required": [ + "id", + "user_id", + "agent_id", + "name", + "description", + "engine", + "status", + "current_version", + "active_version", + "trigger_kind", + "cron_expr", + "next_fire_at", + "hook_key", + "spend_cap_month", + "notify_pref", + "created_at", + "updated_at" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + } + }, + "required": [ + "workflows" + ], + "type": "object" +}
- Changed
run_workflow1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "billed": { + "description": "The billing flag. True only for a user-fault succeeded, failed, or timed-out execution.", + "type": "boolean" + }, + "created_at": { + "type": "string" + }, + "credits": { + "type": [ + "null", + "integer" + ] + }, + "duration_ms": { + "type": [ + "null", + "integer" + ] + }, + "ended_at": { + "type": [ + "null", + "string" + ] + }, + "error": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "fault": { + "description": "Why a non-succeeded execution ended. User means the workflow's own steps or limits. A platform fault is never billed. This field is null when the execution succeeded.", + "type": [ + "null", + "string" + ] + }, + "id": { + "type": "string" + }, + "started_at": { + "type": [ + "null", + "string" + ] + }, + "status": { + "type": "string" + }, + "step_stats": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "steps": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "trigger_source": { + "type": "string" + }, + "workflow_id": { + "type": "string" + } + }, + "required": [ + "id", + "workflow_id", + "status", + "fault", + "billed", + "trigger_source", + "started_at", + "ended_at", + "duration_ms", + "credits", + "created_at" + ], + "type": "object" +}
- Changed
schedule_run1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "agent_id": { + "type": "string" + }, + "attempts": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "fire_at": { + "type": [ + "null", + "string" + ] + }, + "id": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "last_error": { + "type": "string" + }, + "last_fired_at": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "description": "Arbitrary JSON owned by the producing engine." + }, + "prompt": { + "type": "string" + }, + "status": { + "type": "string" + }, + "thread_id": { + "type": "string" + } + }, + "required": [ + "id", + "agent_id", + "kind", + "status", + "prompt", + "attempts", + "created_at" + ], + "type": "object" +}
- Removed
set_agent_model - Added
set_workflow_agent
2 tool updates
v0.9.1- Changed
answer_pending_input1 field changed- added
Input schema / properties / max_turn_secondsAdded value: +{ + "description": "Optional soft wall-clock budget to preserve on the continuation run; it does not change the parked run or impose a hard deadline.", + "maximum": 14400, + "minimum": 0, + "type": "integer" +}
- Changed
invoke_agent1 field changed- added
Input schema / properties / max_turn_secondsAdded value: +{ + "description": "Optional soft wall-clock budget for this turn in seconds (0 or omitted uses forge's deployment default; maximum 14,400). It schedules an in-loop checkpoint and does not cancel the run.", + "maximum": 14400, + "minimum": 0, + "type": "integer" +}
4 tool updates
v0.9.0- Added
cancel_run - Added
edit_workflow - Added
get_workflow_version - Changed
invoke_agent1 field changed- added
Input schema / properties / max_turn_tokensAdded value: +{ + "description": "Optional cumulative cache-weighted token ceiling for this turn (0 or omitted uses forge's default; maximum 5,000,000). The agent reserves its final 2% for a tool-free wrap-up.", + "maximum": 5000000, + "minimum": 0, + "type": "integer" +}
14 tool updates
v0.7.0- Changed
answer_pending_input1 field changed- added
Input schema / properties / always_allowAdded value: +{ + "description": "Approve AND stop asking for this tool on this agent (a standing grant). Only set it when the human explicitly said to stop being asked, and only on a row whose consent_tool is set; ignored without approved=true. Revoke via DELETE /v1/agents/{agent_id}/tool-consents/{tool}.", + "type": "boolean" +}
- Changed
create_agent1 field changed- changed
Input schema / properties / model / descriptionPrevious value: -"Optional model slug; omitted uses Auto, the plan-scaled default whose quality follows the account's plan. An explicit frontier model requires a paid plan."New value: +"Optional model slug; omitted uses the Plori Router, which picks the cheapest model that fits each task from the pool the account's plan unlocks. An explicit frontier model still requires a paid plan."
- Changed
create_workflow1 field changed- changed
Input schema / properties / agent_id / descriptionPrevious value: -"Optional UUID of one of your agents to record as the workflow's creator."New value: +"Optional UUID of one of your agents to own the workflow. That agent is then the one that can build, edit, and run it from a chat; leave it out and the workflow stays unassigned until you set an owner."
- Added
get_agent - Added
get_usage - Added
get_workflow - Changed
invoke_agent1 field changed- changed
Input schema / properties / session_id / descriptionPrevious value: -"Optional thread/session id to continue an existing conversation; omit to start a new one."New value: +"Optional thread/session id to continue an existing conversation (a previous invoke_agent or get_run_result result carries it as \"session_id\"); omit to start a new one."
- Added
list_connections - Added
list_runs - Added
list_workflow_executions - Changed
list_workflows1 field changed- added
Input schema / properties / agent_idAdded value: +{ + "description": "Optional: a UUID of one of your agents to list only its workflows, or \"none\" for the unassigned ones.", + "type": "string" +}
- Added
run_workflow - Added
schedule_run - Added
set_agent_model
13 tool updates
v0.3.0- Changed
create_agent1 field changed- changed
Input schema / properties / model / descriptionPrevious value: -"Optional model slug; omitted uses the account's tier default. Frontier models require a paid plan."New value: +"Optional model slug; omitted uses Auto, the plan-scaled default whose quality follows the account's plan. An explicit frontier model requires a paid plan."
- Removed
get_agent - Changed
get_credits1 field changed- added
Input schema / propertiesAdded value: +{}
- Changed
get_disk1 field changed- added
Input schema / propertiesAdded value: +{}
- Removed
get_usage - Changed
invoke_agent1 field changed- added
Input schema / properties / idempotency_keyAdded value: +{ + "description": "Optional retry guard: a string you generate for this attempt. Re-sending the same key with the same agent and message within 24h returns the ORIGINAL run instead of starting a second one. Reusing a key with a different message is an error.", + "type": "string" +}
- Changed
list_agents1 field changed- added
Input schema / propertiesAdded value: +{}
- Removed
list_brains - Removed
list_runs - Changed
list_workflows1 field changed- added
Input schema / propertiesAdded value: +{}
- Removed
run_workflow - Removed
schedule_run - Removed
set_agent_model
6 tool updates
v0.1.1- Changed
create_agent1 field changed- changed
Input schema / properties / name / descriptionPrevious value: -"A human-readable name for the agent."New value: +"The agent's name. Reusing a previous name returns that existing agent."
- Added
create_workflow - Added
get_workflow_execution - Changed
invoke_agent1 field changed- changed
Input schema / properties / wait / descriptionPrevious value: -"Wait for the turn to complete and return the reply (default true). If false, returns a run_id to poll."New value: +"Wait (up to ~25s) for the turn and return the reply (default true). Set false to return a run_id immediately and poll get_run_result — prefer this for long or tool-heavy turns so the call doesn't block your own turn."
- Added
list_workflows - Added
run_workflow
15 tool updates
v0.1.0- First observed
answer_pending_input - First observed
create_agent - First observed
delete_agent - First observed
get_agent - First observed
get_credits - First observed
get_disk - First observed
get_run_result - First observed
get_usage - First observed
invoke_agent - First observed
list_agents - First observed
list_brains - First observed
list_pending_inputs - First observed
list_runs - First observed
schedule_run - First observed
set_agent_model
TDQS
Scored across 25 tools
Tools are organized into clear resource domains — agents, workflows, runs, billing/disk, and OAuth — so most choices are obvious. The main ambiguity is get_workflow vs get_workflow_version, and to a lesser extent get_agent vs create_agent's get-or-create behavior, which an agent could misselect despite helpful cross-references.
All tools follow a consistent verb_noun snake_case pattern: create_agent, list_workflows, cancel_run, empty_trash, answer_pending_input. The get/list split is applied uniformly across agents, workflows, and executions, making the naming predictable.
At 25 tools, the server sits at the heavy end of the scale. Each tool is individually justified by the broad scope — agents, workflows, runs, billing, disk, and connections — but the total surface feels more like several subdomain APIs bundled together than a tightly scoped set.
Agent and run lifecycle coverage is strong, but the workflow lifecycle has notable gaps: there is no delete_workflow, and no explicit activate/publish tool even though edit_workflow warns that edits do not activate the draft. Billing, disk, and connection surfaces are read-mostly, which is acceptable but leaves workflow management incomplete.
Maintenance
Related MCP Connectors
Hosting for AI agents: your AI client deploys Docker apps to live HTTPS URLs over MCP.
Hosted runtime for persistent agent teams, durable workflows, memory, schedules, and goals.
MCP-first control plane for ProAgentStore agents and private instances.
Remote MCP server for supportsheep: run AI interviews and manage support content for your blog.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceMulti-project execution, memory, and collaboration platform for humans and AI agents, providing MCP tools for agents to read and write project state.3MIT
- AlicenseAqualityDmaintenanceAgent-native hosting: your agent deploys any folder to a live URL in one command — no account, no dashboard, no CAPTCHA — and hands the human a link plus a plain-language summary. Full deploy lifecycle as MCP tools (deploy, verify, logs, inspect, rollback), production approval human-only; static sites and full Node.js apps, open source (Apache-2.0).13Apache 2.0

PoYo MCP Serverofficial
AlicenseNot gradedqualityBmaintenanceLocal stdio bridge to the hosted PoYo MCP server, enabling discovery and execution of AI models via chat, generation tasks, and agent skills.1MIT- AlicenseAqualityAmaintenanceOutbound-only remote shell, detached long-running jobs, and temporary file courier for AI agents. Hosted Streamable HTTP plus stdio via npx -y @aicommander/mcp.11MIT