Plori
OfficialPlori's remote MCP server lets you create, run, and manage persistent cloud AI agents, their runs, human approvals, workflows, and account resources.
Agents: list/get agents; get-or-create by name; delete an agent and revoke its disk.
Runs: invoke an agent with a message (wait or poll); get run result with status, timing, credits, tokens, files, errors; list run history; cancel a run; schedule a one-shot deferred run.
Human-in-the-loop: list runs paused for approval/input; answer a pending request (approve/deny, provide input, set standing or thread-scoped tool consent).
Workflows: list/get workflows; get exact versions; create manual/cron/webhook workflows; edit as draft with compare-and-swap; assign an agent; run now; inspect executions and per-step payloads.
Account: get credit balance/plan; get usage by role, meter, agent, workflow and recent runs; get disk usage; empty an agent's trash; list third-party OAuth connections.
Connection: use as a remote streamable-HTTP MCP server via OAuth or API key; no local install.
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: PoYo MCP Server
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; it returnsawaiting_confirmationand aconfirm_url, and the run is queued only after you confirm it in the Plori web app).Human-in-the-loop:
list_pending_inputs(runs paused on an approval or an input request),answer_pending_input(deny one, or answer an agent's question, which starts a continuation run). An MCP client cannot approve an action: each paused approval carries anapprove_urlthat you open in the Plori web app.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). Use approved=false to deny an action, or value to answer a question. Only the account owner can approve an action in the Plori web app. Show them the pending input's approve_url. Never ask for or submit a secret value through this tool. Use the Plori web app for secrets and connections. 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. | |
| value | No | For an input request: the value to supply. | |
| run_id | Yes | The parked run's id. | |
| approved | No | For an approval request: set false to deny. Only the owner can approve in the Plori web app. | |
| 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?
Annotations already declare destructiveHint=true, non-idempotent, and openWorld, so the safety profile is covered. The description adds genuinely non-structured context: that only the account owner can approve (in the web app), that secrets must not be passed here, and that a successful answer spawns a continuation run. This is strong added value beyond 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?
Front-loaded with the action and the sibling reference, then flows through denial, auth constraint, secret exclusion, and return semantics. Every sentence carries a distinct actionable fact 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?
An output schema exists so return values need not be explained, yet the description still clarifies the one thing that would otherwise confuse an agent: which run_id to poll afterwards. Combined with auth and secret guidance, nothing needed to invoke 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 coverage is 100%, so the 3 baseline applies, but the description adds meaning beyond the schema: the deny semantics of approved=false, value being the question answer, and critically the note that the returned run_id is the continuation run's id, not the parked run's. That resolution of the run_id ambiguity is real added value.
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 ('Answer a run that is paused on a human-input request') and immediately cross-references the sibling list_pending_inputs that produces the required tool_call_id. An agent can place it precisely among siblings like list_pending_inputs, cancel_run, and get_run_result.
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 explicit routing: approved=false to deny, value to answer a question, and a clear exclusion for secrets/connections ('Use the Plori web app for secrets and connections'). It also names the follow-up tool (get_run_result) needed after a successful answer.
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?
Annotations already declare destructiveHint=true, non-idempotent and non-readOnly, but the description adds substantially more: cancellation is asynchronous, a success returns status "cancelling" rather than a terminal state, the caller must poll get_run_result, and finished runs are rejected. That is exactly the behavioral context annotations cannot 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 tight sentences: the action, the asynchronous contract with the exact status strings, and the failure precondition. Nothing is redundant and the key constraint 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 two-parameter mutation with an output schema present, the description supplies everything an agent needs: the async lifecycle, the intermediate status value, the polling tool to use, and the non-cancellable case. Return-value details are correctly left to the output schema.
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 both required parameters (run_id, agent_id) are documented in-schema, so the baseline is 3. The description adds no additional meaning about parameter formats or constraints.
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 ("Stop an in-flight agent run") that unambiguously distinguishes it from siblings like invoke_agent, list_runs, and get_run_result. An agent can identify the operation without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the exclusion condition explicitly ("A run that already finished cannot be cancelled") and routes the agent to the follow-up tool ("poll get_run_result until the run becomes 'cancelled'"). Both when-to-use and what-to-do-next are spelled out.
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?
The description adds substantial behavioral context beyond the annotations: it explains the agent's persistent state (disk, tools, memory), that repeated calls are safe and return the existing agent marked with 'existing': true, and that creation is subject to the account's agent-count limit. It also notes that the Plori Router chooses the model per task.
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 definition, then proceeds through creation criteria, exclusions, idempotency behavior, quota limits, and model routing. Every sentence contributes actionable context, and there is no filler 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?
Given the single parameter, full schema coverage, the presence of an output schema, and annotations that cover safety hints, the description is complete. It explains when to create or reconnect, idempotent behavior, quota constraints, and model routing, leaving no material gaps 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?
With one parameter and 100% schema description coverage, the schema already documents that 'name' identifies the agent and that reusing a previous name returns the existing agent. The description repeats this semantic without adding format or constraint details beyond what the schema provides, 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 opens with a precise verb and resource: 'Get or create an agent by name', and immediately defines the agent as a persistent cloud environment with disk, tools, and memory. It clarifies that the operation is idempotent and returns an existing agent instead of duplicating, making it distinguishable from pure creation or listing 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 gives explicit when-to-use conditions ('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') and when-not conditions ('a question you can answer yourself or for a one-off script with no state worth keeping'). It does not name a specific sibling tool as an alternative, but the selection context is clear.
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?
Annotations only declare the write/non-idempotent/non-destructive profile. The description adds real behavioral context: the workflow starts with no steps and cannot run until its owning agent builds them, the trigger_kind/cron_expr can be overridden later by a schedule or webhook step, and a webhook trigger exposes a public hook URL.
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?
Purpose and return value are front-loaded, then trigger semantics, then the lifecycle caveat. Every sentence carries a distinct constraint, though the trigger_kind behavior is restated enough that a slight trim would help.
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 full picture an agent needs: what is created, the trigger options and their prerequisites, the ownership model, and the fact that a freshly created workflow is inert until built. With an output schema present, return detail is not required, making this 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%, so baseline is 3. The description goes beyond it by stating the default ('manual'), the cron_expr dependency on trigger_kind='cron', and the non-obvious fact that a schedule written only in the description field is ignored.
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 qualifies scope with 'empty', plus what it returns. An agent can distinguish it from create_agent or edit_workflow without inspecting either schema.
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 conditional guidance for each trigger_kind (manual -> run on demand with run_workflow; cron -> needs cron_expr; webhook -> mints a public hook URL) and warns that trigger_kind is not read from description. It does not explicitly contrast with edit_workflow or set_workflow_agent, so it stops just short of explicit alternatives.
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?
Annotations only flag destructiveHint and idempotentHint; the description goes well beyond that by disclosing irreversibility ('cannot be undone'), the side effect on the agent's disk, and the precise blast radius for workflows — not deleted, live ones paused, blocked until reassigned. That is exactly the context an agent needs before committing an irreversible action.
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 tight sentences, front-loaded with the core action and the irreversibility warning before the workflow nuance. Every sentence carries distinct, decision-relevant information.
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 need no explanation, and the description covers the action, reversibility, and cross-entity side effects. Nothing needed to call this destructive tool safely 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 is one parameter and schema coverage is 100%, so the schema already fully documents agent_id as the UUID to delete. The description adds no format or sourcing detail beyond the schema, 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?
States a specific verb and resource ('Permanently delete an agent') plus a secondary effect ('revoke its disk'), which cleanly separates it from read/list siblings like get_agent and list_agents and from 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?
Consequences are well described, but there is no explicit guidance on when to delete versus alternatives such as cancel_run or reassigning the agent via set_workflow_agent. Usage is implied by the destructive framing rather than stated.
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 declare destructiveHint=true and idempotentHint=true; the description adds crucial context beyond them: the compare-and-swap conflict behavior, that edits are applied atomically in order, and that editing does not activate the draft. This is exactly the kind of behavioral detail annotations can't 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 tight sentences, front-loaded with the core action, followed by the critical usage constraint and the activation non-behavior. No wasted words.
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 high schema coverage and the presence of an output schema, the description provides everything needed: the transactional model, the required precondition, the supported op set, and the fact that it creates a draft rather than activating. 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?
Schema description coverage is 100%, so the schema already documents every parameter and nested op property in detail. The description adds a high-level listing of supported ops (set_params, add_step, remove_step, add_router) and the semantics of base_version, which helps orient the agent before reading 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?
States a specific verb (Apply a batch of constrained edits), resource (workflow definition as a new draft version), and the mechanism (base_version compare-and-swap). Clearly distinguishable from siblings like get_workflow_version, create_workflow, and run_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?
Explicitly instructs the agent to read the current definition with get_workflow_version first, and explains that a stale base_version is rejected. It doesn't name other editing alternatives, but the workflow is clear.
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, but the description adds the key operational context: permanent deletion, trash still consumes disk until called, and the asleep/idle precondition. This is beyond what the annotations carry.
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 dense sentences with no waste. It front-loads the action, then the disk-accounting rationale, then the precondition in a single clause.
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 output schema exists, return values needn't be explained. The description covers the destructive nature, the precondition, and where to check freed bytes, leaving nothing an agent needs to call 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 single parameter is documented as the agent's UUID, so the schema does the heavy lifting. The description adds no additional parameter detail, making the baseline 3 correct.
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 ('Permanently empty') and resource ('one agent's trash'), and scopes it to a single agent. Distinguishes it from delete_agent by clarifying that deleted files go to trash and are only reclaimed here.
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 names the precondition (agent's pod must be asleep) and the failure mode (error asking you to wait ~two minutes of idle or cancel the run first). Routes the agent to get_disk's trash_bytes to see what a call would free.
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 openWorldHint=false, so safety is covered, and the description still adds substantive behavioral context: the mailbox is scoped to same-account mail from other agents, is ordered (open letters first by status group, newest within group), and is capped at 20. That ordering and truncation disclosure is genuinely useful beyond 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?
A single dense sentence with the primary purpose front-loaded and the mailbox caveats trailing. Every clause adds information (fields, ordering, cap), though the mailbox clause makes it longer than strictly needed for a getter.
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-value documentation is not required, yet the description still characterizes the mailbox payload and its limit. With the single parameter fully documented in the schema, an agent has everything needed to call this correctly; only explicit sibling routing 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 is only one parameter and schema description coverage is 100% ('The agent's UUID (from list_agents or create_agent)'), so the schema already carries the full meaning. The description adds only the phrase 'by its id', so 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?
States a specific verb ('Get') and resource ('one agent's details') and enumerates exactly which fields are returned (name, type, model, status) plus the mailbox payload. The singular 'one agent ... by its id' implicitly but clearly separates it from the sibling list_agents.
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 retrieval scope is clear enough to imply when to call it (you have an agent id and want that agent), but there is no explicit when-to-use/when-not guidance and no named alternative such as list_agents or get_run_result. Usage is inferred rather than directed.
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?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds genuinely useful behavioral context beyond that: the balance is prepaid and consumed by running agents. It stops short of describing freshness/latency or update cadence, so not a full 5.
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 tight sentences, front-loaded with the core purpose, followed by the 'why check' motivation and the alternative-tool routing. Every sentence earns its place 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 zero-parameter read tool with an output schema present, the description needs only purpose, usage context, and routing to alternatives, all of which it supplies. Nothing an agent needs to invoke it 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?
Zero parameters, so the baseline is 4. The description does mention balance_usd, but that refers to a return field already covered by the output schema, not a parameter, so there is no additional parameter meaning to convey.
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 (Get) and resource (authenticated account's US-dollar balance and plan), and explicitly distinguishes itself from the sibling get_usage. An agent can tell this apart from other read tools without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('check it before invoking' since running agents spend the balance) and names the alternative tool plus the condition that selects it ('For where the money went, use get_usage instead'). Nothing is left to inference.
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 |
|---|---|---|
| agents | No | The account's Agents that have a disk, largest used_bytes first: where the account's usage is and how much of each Agent's is trash. |
| 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 and openWorldHint=false, so the safety profile is covered. The description adds that the data is for the authenticated account and enumerates the fields returned, which is useful behavioral context, but it does not address rate limits, pagination, or other operational traits.
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 a single, well-structured sentence that front-loads the verb and resource. Every clause adds specific value by listing the disk metrics returned, with no wasted words.
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 simple, parameterless read operation with annotations and an output schema, the description is nearly complete. It states the account context and the key returned fields, though it could optionally clarify when to prefer it over related tools like get_usage.
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 baseline of 4 applies. There are no parameter semantics for the description to clarify beyond 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 states a specific verb and resource: 'Get the authenticated account's disk state.' It also names the exact data elements returned, which makes the purpose clear. However, it does not distinguish this tool from sibling reads such as get_usage or get_credits, so it lacks explicit sibling differentiation.
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 like get_usage or get_credits. It simply states what the tool returns, leaving context and exclusions unstated.
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 resultARead-onlyInspect
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 pending requests. Show the owner each approval request's approve_url. 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?
Annotations only declare readOnly/idempotent. Description adds substantial context beyond them: wait semantics and hold contract, files returned as absolute URLs fetched with the same bearer token, failed-run retryability and charging info, awaiting_input flow with continuation_run_id, and polling stopping conditions. This is exactly the value-add behavioral disclosure expected.
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?
Dense but front-loaded with the result contents. Some sentences are long (the wait clause, the completion clause). Every sentence carries information, but it's tight to the point of being hard to scan; structure is functional but not clean.
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 needn't be fully explained, yet the description goes further to describe status-specific behaviors (awaiting_input, failed, cancelled) and continuation_run_id. For a complex polling tool, this is nearly complete, though a note on auth requirements for the run itself would round it out.
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 baseline is 3. The description adds meaning: wait=true holds the turn until terminal/input/expiry, wait_seconds bounds it, and run_id is qualified elsewhere. Slightly above baseline by tying wait's effect to the server-instructions contract.
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?
Specific verb+resource (get a run's status/result) with rich enumeration of returned fields. Clearly distinguished from siblings like list_runs (plural) and get_workflow_execution. An agent knows exactly what this returns.
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 to keep polling non-terminal runs at poll_after_seconds, and to stop polling after cancelled/expired input. States wait=true behavior. Lacks explicit when-NOT-to-use framing (e.g., use list_runs to discover run_ids first), but the polling guidance is strong.
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?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safe-read profile is covered without description help. The description adds some behavioral context by describing the shape of the rollup (spend by role/meter/agent plus recent runs), but says nothing about scope limits, time windows, or freshness. Adequate but not rich beyond 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 tight sentences, both load-bearing: the first defines the resource and payload, the second routes to the sibling. The primary purpose is front-loaded with zero preamble.
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, return values need not be explained, and the description correctly focuses on purpose and tool selection. A zero-parameter read tool is essentially fully specified; only minor detail (e.g., which period the rollup covers) is absent.
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 takes zero parameters, so the baseline of 4 applies; there is no parameter detail the description could add or is missing.
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 (get) and resource (usage rollup) scoped to 'the authenticated account's', then enumerates what the rollup contains (US-dollar spend by role, meter, and agent, with recent runs). This clearly separates it from siblings like get_credits and list_runs.
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 an explicit use case ('answer where the money went') and names the alternative tool with its selecting condition ('for the current balance use get_credits'). Routing between the two financially-themed siblings is unambiguous.
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 and openWorldHint=false, so the safety profile is covered. The description adds genuinely useful behavior beyond that: which version the returned projection reflects (active_version, falling back to current_version for an unactivated draft). This is exactly the kind of non-obvious resolution logic annotations cannot express.
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 tight sentences, front-loaded with the core action and followed by the one non-obvious rule. No filler, no restating of the title, nothing to trim.
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 document return values, and it is complete for a single-ID read. It omits edge behavior such as what happens for an unknown or deleted workflow_id, which is a minor gap rather than a blocker.
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 is a single parameter with 100% schema description coverage, and the schema already explains that workflow_id is a UUID sourced from list_workflows or create_workflow. The description adds nothing further about the parameter, so the 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?
States a specific verb+resource (get one workflow) and clarifies exactly what is returned: metadata plus a step projection resolved from active_version. The version-fallback explanation implicitly distinguishes it from get_workflow_version and list_workflows, but no sibling is named explicitly, so it falls just short of a 5.
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 never says when to reach for this tool versus get_workflow_version, get_workflow_execution, or list_workflows, nor does it state any prerequisites (e.g., needing an ID from list_workflows). Usage is only minimally inferable from the phrase 'Get one workflow's...'.
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 carry the safety profile (readOnlyHint=true, openWorldHint=false), so the bar is lower, yet the description still adds non-obvious domain behavior: fault is null on success, and a platform fault is never billed. It does not cover polling cost, rate limits, or whether repeated polls are free, which keeps it short of a 5.
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 most important fact (what is returned) is front-loaded and the sibling differentiator closes the text. It is terse and readable, though 'billed is the billing flag' is close to filler and adds no information.
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 enumerate return values, and it instead supplies the semantic glosses an agent needs (fault, user limits, platform faults unbilled). The cryptic line 'user means the workflow's own steps or limits' is under-explained, leaving a small gap for a tool described as returning per-step payloads.
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 both parameters are documented in the schema (workflow_id UUID, execution_id from run_workflow). The description adds nothing about either parameter, so the baseline 3 for a fully-covered two-param schema 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 opening sentence gives a specific verb (Get) and resource (one workflow execution) plus the exact scope of data returned: status, billing, timing, credits, and per-step payloads. The final sentence explicitly separates it from the closest sibling, list_workflow_executions, so an agent can distinguish them without opening 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?
It states the use case directly ('Use this tool to poll a run or inspect each step') and names the alternative with the condition that selects it ('list_workflow_executions omits step payloads'). The routing decision between the two tools is fully determined by the description.
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 and openWorldHint=false, so the safety profile is covered. The description adds real value by disclosing the returned content shape ('full builder definition with step parameter values and its value-light projection'), which goes beyond the structured fields, though it says nothing about pagination or payload size.
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 tight sentences, front-loaded with the resource and payload, followed by the routing guidance. 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?
An output schema exists, so return values need not be enumerated; the description nonetheless characterizes the payload. Combined with 100% parameter coverage and existing annotations, nothing an agent needs to invoke this 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 coverage is 100% and both parameters are fully documented in the schema (positive version number, workflow UUID). The description adds no syntax or format detail beyond what the schema already provides, so the 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?
States a specific verb ('Get') and resource ('one exact workflow version') and details what the payload contains (builder definition with step parameter values and value-light projection). This clearly distinguishes it from the sibling get_workflow, which returns the current workflow rather than a pinned version.
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 routes the agent: 'Use current_version from get_workflow unless you intentionally need an older version.' This names the alternative tool and the exact condition (fetching a historical version) that selects this one.
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 paused run returns status "awaiting_input" with the request inline. Show the owner each approval's approve_url. Each external write pauses for the owner's approval in the Plori web app. The calling model cannot approve it. Use answer_pending_input to deny an action or answer a question. 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?
The annotations declare destructive=true, openWorld=true, idempotent=false, readOnly=false, so the bar is high, but the description goes well beyond them: it discloses the pricing/credits model, idempotency_key retry semantics (including double-billing if omitted), the pause-for-owner-approval flow, the running vs completed result fields, the 429 concurrency cap, and that the calling model cannot approve. This is rich, non-contradictory behavioral 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?
The description is front-loaded with the core purpose and outcome, then flows through retry, approval, and cost guidance in a logical order. It is long (a dense paragraph) but every sentence carries operational value; only minor tightening would improve it.
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?
It covers the full lifecycle: synchronous vs polling modes, retry safety, approval interrupts, concurrency limits, cost shaping, and continues via session_id. With an output schema also present, the description is more than complete for an agent to call 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 the schema already documents all 11 parameters in detail; the description adds little parameter syntax or format info beyond what the schema provides. It does mention idempotency_key, max_turn_tokens, and session_id in context, which links them to practical workflows, but baseline 3 is appropriate when the schema does the heavy lifting.
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 ('Send a message to an agent and return its reply, or a running run_id'), immediately distinguishing the two outcomes. It implicitly contrasts with get_run_result (the polling sibling) and lists concrete use cases (files written now and read later, long jobs) that differentiate it from list_agents or get_agent. An agent can confidently tell this apart from its siblings.
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 clear when-to-use guidance ('work that should outlive a single request') with examples, and explicit alternatives: poll with get_run_result, use answer_pending_input to deny or answer, and set wait=false for long turns. It even specifies the fallback behavior on 429 (wait for a run to finish and retry). This is textbook usage guidance.
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?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds genuine non-obvious context: results are ordered newest first, what fields come back, and the important caveat that an empty model is not an error because effective_model / plori-auto resolve routing at run time.
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, both front-loaded and non-redundant: the first delivers purpose/scope/ordering, the second resolves a real ambiguity about a sentinel output value. 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 zero-parameter, read-only listing tool with an output schema, this is more than adequate – the return shape is documented elsewhere and the description supplies the interpretation nuance an agent would otherwise get wrong.
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 takes zero parameters, so the schema imposes no semantic burden and the baseline is 4. Nothing in the description is needed to disambiguate inputs.
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 a specific verb and resource ('List the agents'), scopes it precisely ('owned by the authenticated account'), and states ordering ('newest first') plus the fields returned. That scope cleanly separates it from the singular get_agent sibling, so an agent can pick it without opening either schema.
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?
Usage is implied by 'list the agents owned by the authenticated account' – a reasonable agent infers it should be used to enumerate agents. However, there is no explicit when-to-use/when-not guidance and no mention of the get_agent alternative for fetching a single agent's detail.
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?
Annotations already mark it read-only, but the description adds substantial context beyond them: which fields are returned, that needs_reauth is the actionable flag while status is a spelled-out equivalent, that authorized rows may have a past expires_at due to lazy refresh, and that token/client-secret material is never 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?
Front-loaded with what is listed before the interpretive detail, and the expires_at caveat is genuinely load-bearing rather than filler. It is dense and slightly run-on in the 'Never derive it from expires_at' stretch, but no sentence is wasted.
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?
Despite an output schema being present (so return shapes need not be explained), the description front-loads the field-level semantics an agent needs to act on the result, including the reauth decision tree and the lazy-refresh/null-expiry edge cases. Nothing needed to call or interpret it 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?
Zero parameters, so there is nothing to document and the baseline of 4 applies. No parameter syntax or meaning is missing.
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 (List) and resource (authenticated account's third-party OAuth connections) plus the exact fields surfaced (provider status, authorization/expiry times, configured scopes). No sibling overlaps with this resource, so an agent can identify it immediately.
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?
No explicit when-to-use or when-not-to-use guidance and no alternatives named, though none of the siblings compete for this resource. It spends its words on how to read the result (needs_reauth, status) rather than routing, leaving usage implied.
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). For an approval, show the account owner its approve_url. Only the owner can approve it in the Plori web app. 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?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds real context beyond that: the approve_url is shown to the account owner, only the owner can approve in the Plori web app, and superseded turns are silently dropped from the list.
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 sentences, front-loaded with the what, followed by owner/approval mechanics and the exclusion rule. Every sentence carries information; slightly dense but 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?
An output schema exists, so return values need no explanation. The description covers the queue definition, owner authorization, the approve_url, and the superseded-turn filter — everything an agent needs to call and interpret this 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?
There is one parameter with 100% schema description coverage ('The agent's UUID'), so the schema carries the semantics. The description adds nothing about agent_id, which is acceptable at this coverage level but no better than baseline.
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+resource with scope: runs 'paused awaiting a human approval or input (the HITL queue)'. This clearly separates it from the sibling list_runs, which has no such filter, and names the domain concept (HITL queue) an agent can key on.
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 the selection condition (paused awaiting human approval/input) and an explicit exclusion ('a request whose session has already moved on is not listed... answering it would resume a superseded turn'). It does not explicitly name the complementary sibling answer_pending_input at the point of use, but the context is unambiguous.
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 readOnlyHint/idempotentHint/openWorldHint; the description adds substantial behavior beyond that: default/max page size, next_cursor contract, the session_id==thread_id equivalence, and the semantics of tool_progress (null for terminal or no-telemetry runs, otherwise matching get_run_result). The input_expired explanation is exactly the kind of non-obvious state semantics that would otherwise be discoverable only by trial.
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?
Front-loaded with purpose, then paging, then per-row semantics, then the input_expired edge case — a logical order. It is a dense paragraph rather than a list, but each clause carries new information and nothing appears to be 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?
Covers purpose, ordering, paging, key output fields, cross-tool linkage (invoke_agent, get_run_result), and the one genuinely confusing row state (input_expired). Given an output schema and full annotation coverage, this is complete enough for correct invocation without opening other tools.
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 each parameter is documented, so baseline is 3. The description restates the limit default/max and the cursor round-trip in prose, which reinforces but does not meaningfully extend the schema 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?
States a specific verb and resource ('List an agent's run history') and immediately specifies sort order and the fields returned (status, timing, attributed cost). An agent can distinguish this from list_agents, list_pending_inputs, or get_run_result from the description alone.
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 names the sibling tools and their relationship: session_id 'continues that conversation through invoke_agent', and input_expired rows should lead the agent to 'start a new run rather than answering it' — routing away from answer_pending_input. It also defines the pagination stop condition (when next_cursor is absent).
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 executionsBRead-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 already declare readOnlyHint=true, openWorldHint=false and idempotentHint=false, so the safety profile is covered. The description adds useful domain semantics ('a platform fault is never billed', 'fault is null when the execution succeeded'), but those are return-field semantics that the existing output schema should carry, and it discloses no operational traits such as result caps, ordering guarantees, or auth requirements.
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?
Front-loaded with the action and ordering, then short field notes. A few sentences approach tautology ('billed is the billing flag'), which is minor waste but keeps the whole description compact.
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 one-parameter read tool with full schema coverage and an output schema, an agent has what it needs to invoke it. The remaining gap is only the absence of any statement about how many executions are returned or how to page.
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 workflow_id parameter is fully documented in the schema (UUID from list_workflows or create_workflow). The description adds nothing about the parameter, 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?
States a specific verb and resource with scope ('a workflow's recent executions') and ordering ('most recent first'), which separates it from the single-record get_workflow_execution sibling. It does not, however, explicitly contrast itself with list_runs or other list 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?
No when-to-use guidance, no exclusions, and no routing to get_workflow_execution for a single execution or to list_runs for a different resource. The 'recent' wording implies a bounded default list but never states a limit or pagination behavior.
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 and openWorldHint=false, so safety is covered. The description adds ownership/permission context beyond the annotations — each workflow belongs to one agent and only that agent can edit or run it — which materially affects interpretation of the results, though pagination and result-size behavior are unstated.
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 front-loaded sentences that stay on topic: scope, ownership rule, then the filter. The agent_id filter is stated twice (narrative and sentinel form), which is mild redundancy but not padding.
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 one optional parameter, read-only annotations, and an existing output schema, the description covers everything an agent needs: what is listed, whose workflows, and how to filter. Return-value documentation is correctly left to the output schema.
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 is fully documented there, including the "none" sentinel, so the baseline is 3. The description largely restates that same semantics rather than adding syntax or format detail.
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+resource (list workflows) plus scope (owned by the authenticated account) and the fields returned (status, trigger, version, agent_id). An agent can distinguish it from list_agents and get_workflow immediately.
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?
Explains how to narrow the result set with agent_id and the sentinel agent_id="none" for unassigned workflows, which is real when-to-use guidance. It does not name the sibling that serves single-workflow lookups (get_workflow), so it stops short of full alternative routing.
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?
Annotations already flag destructive/non-idempotent/open-world, and the description goes further: it discloses billing (flat per-execution fee plus model usage), that the call waits briefly, and that non-terminal results must be polled. This is meaningful cost and lifecycle context beyond the structured hints.
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 tightly packed sentences, front-loaded with the core action and side-effect warning, then cost, then completion semantics. 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 mutating, billable, asynchronous execution tool, the description covers cost, side effects, prerequisites, and how to handle a non-terminal response. An output schema exists, so return-value detail is correctly left to it.
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 workflow_id and trigger_payload are already documented in the schema. The description adds no parameter-level syntax or format detail, which is acceptable given the schema carries that burden.
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+resource ('Run a workflow now') and immediately qualifies it as a real execution with real side effects, distinguishing it from scheduling, listing, or fetching executions among the siblings.
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 the prerequisite ('the workflow must already have steps') and routes the agent to get_workflow_execution for polling when the run is not yet terminal. It does not explicitly contrast with schedule_run for deferred/recurring runs, 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
Request a one-shot deferred run of an agent, billed like any run. The schedule is not queued until the account owner confirms it in the Plori web app. Show the owner the prompt, time and confirm_url. The calling model cannot confirm it. 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 | |
| confirm_url | No | |
| confirmed_at | No | |
| last_fired_at | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructive=false/true semantics and non-idempotency, but the description adds the behavioral facts that matter most: the schedule is not queued until the account owner confirms in the web app, the calling model cannot confirm it, the call is billed like a normal run, and the model should surface prompt/time/confirm_url to the owner. This is exactly the beyond-annotation context the dimension rewards.
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?
Five tight sentences, front-loaded with the high-stakes fact (deferred, billed, needs owner confirmation) before the parameter mechanics and the sibling routing note. No filler sentences.
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, return values need no explanation. For a mutation tool with a human-in-the-loop gate, the description covers billing, the confirmation requirement, who can confirm, what to show the owner, the mutually exclusive time parameters, and the recurring-schedule 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?
Schema coverage is 100%, so all five parameters are already documented in the schema, including the mutual exclusivity of fire_at and delay_seconds. The description restates that exclusivity but adds no format or constraint detail beyond the schema, so the 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?
States a specific verb and resource ('Request a one-shot deferred run of an agent') and immediately scopes it against the recurring alternative (create_workflow with a cron trigger). An agent can distinguish this from invoke_agent, run_workflow, and create_workflow without opening a schema.
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 says when to use this (one-shot deferred) versus the named alternative (recurring via create_workflow), plus the required alternative between delay_seconds and fire_at. It also flags the human confirmation gate as a precondition, which is the kind of routing information most definitions omit.
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 agentADestructiveIdempotentInspect
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?
Annotations already declare destructiveHint=true and idempotentHint=true, so the safety profile is partly covered. The description adds meaningful concurrency behavior: omitting base_version triggers a read of the current version, and a stale version is rejected with the current version returned. It does not clarify what the destructive aspect is (e.g., whether an existing agent is replaced), so it falls short of a 5.
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, zero filler, with the primary action front-loaded and the conditional triggers and version behavior following in order of relevance.
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?
Output schema and rich annotations carry the return-value and safety burden, and the description supplies triggers plus version semantics. The one gap is not stating the effect on any currently assigned agent, which matters for a destructive mutation.
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, but the description goes beyond the schema by explaining base_version's optimistic-concurrency semantics: omission means read-then-assign, and a stale value is rejected with the current version. That is real added meaning for the least obvious parameter.
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: 'Assign one of your agents to a workflow.' Clear enough to distinguish from siblings like create_workflow or run_workflow, though it does not explicitly contrast itself against a competing assignment tool.
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 explicit triggers: 'Use this after delete_agent reports paused workflows, or when run_workflow returns workflow_agentless.' It names the exact sibling tools and the conditions that route the agent here, leaving little to inference.
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.17.0- Changed
answer_pending_input3 fields changed- removed
Input schema / properties / always_allowRemoved 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
Input schema / properties / approved / descriptionPrevious value: -"For an approval request: approve (true) or deny (false)."New value: +"For an approval request: set false to deny. Only the owner can approve in the Plori web app." - removed
Input schema / properties / scopeRemoved 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
empty_trash1 field changed- added
Output schema / properties / disk / properties / agentsAdded value: +{ + "description": "The account's Agents that have a disk, largest used_bytes first: where the account's usage is and how much of each Agent's is trash.", + "items": { + "additionalProperties": false, + "properties": { + "agent_id": { + "description": "The Agent's UUID.", + "type": "string" + }, + "agent_name": { + "description": "The Agent's name.", + "type": "string" + }, + "asleep": { + "description": "True when the Agent has no running session, which emptying its trash requires.", + "type": [ + "null", + "boolean" + ] + }, + "trash_bytes": { + "description": "How much of used_bytes emptying this Agent's trash would free. Absent when it has not been measured.", + "type": [ + "null", + "integer" + ] + }, + "used_bytes": { + "description": "Bytes this Agent's disk holds, trash included.", + "type": "integer" + } + }, + "required": [ + "agent_id", + "agent_name", + "used_bytes" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
get_disk1 field changed- added
Output schema / properties / agentsAdded value: +{ + "description": "The account's Agents that have a disk, largest used_bytes first: where the account's usage is and how much of each Agent's is trash.", + "items": { + "additionalProperties": false, + "properties": { + "agent_id": { + "description": "The Agent's UUID.", + "type": "string" + }, + "agent_name": { + "description": "The Agent's name.", + "type": "string" + }, + "asleep": { + "description": "True when the Agent has no running session, which emptying its trash requires.", + "type": [ + "null", + "boolean" + ] + }, + "trash_bytes": { + "description": "How much of used_bytes emptying this Agent's trash would free. Absent when it has not been measured.", + "type": [ + "null", + "integer" + ] + }, + "used_bytes": { + "description": "Bytes this Agent's disk holds, trash included.", + "type": "integer" + } + }, + "required": [ + "agent_id", + "agent_name", + "used_bytes" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
get_run_result1 field changed- added
Output schema / properties / pending_inputs / items / properties / approve_urlAdded value: +{ + "type": "string" +}
- Changed
invoke_agent1 field changed- added
Output schema / properties / pending_inputs / items / properties / approve_urlAdded value: +{ + "type": "string" +}
- Changed
list_pending_inputs1 field changed- added
Output schema / properties / pending_inputs / items / properties / approve_urlAdded value: +{ + "type": "string" +}
- Changed
schedule_run2 fields changed- added
Output schema / properties / confirm_urlAdded value: +{ + "type": "string" +} - added
Output schema / properties / confirmed_atAdded value: +{ + "type": [ + "null", + "string" + ] +}
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
Each tool targets a distinct resource and action, with clear boundaries between agents, runs, workflows, executions, billing, disk, and connections. The few potentially confusable pairs (e.g., get_run_result vs get_workflow_execution, invoke_agent vs run_workflow) are well-differentiated by their descriptions and operate on different entities.
All tool names follow a consistent verb_noun snake_case pattern (list_agents, create_workflow, get_run_result, etc.). Minor singular/plural variations (answer_pending_input vs list_pending_inputs) are logically motivated and do not break the pattern.
With 25 tools, the set is on the heavy side, but each tool earns its place given the platform's breadth: agent lifecycle, run management, workflow CRUD and execution, billing, disk, and connections. No tool appears redundant or trivial, though the count is at the upper bound of comfortable.
Core operations for agents, runs, workflows, billing, and disk are well covered. Minor gaps exist, such as no delete_workflow, no cancel_workflow_execution, and no update_agent for renaming or reconfiguring, but these are edge cases that agents can likely work around or that are intentionally handled elsewhere.
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

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- AlicenseAqualityBmaintenanceOutbound-only remote shell, detached long-running jobs, and temporary file courier for AI agents. Hosted Streamable HTTP plus stdio via npx -y @aicommander/mcp.111MIT
- AlicenseNot gradedqualityCmaintenanceHost apps built with AI: deploy to a live HTTPS URL, custom domains, managed sign-in, secrets and backups. Hosted remote MCP server at https://softkiln.com/mcp/ — this repository is its plugins and skills.MIT