Skip to main content
Glama

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 plori

Codex 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/mcp

API 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, with wait_seconds to set how long to hold, idempotency_key to make a retry return the original run, and callback_url plus callback_secret to 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 reports cancelling and then cancelled), schedule_run (invoke an agent once later, after a delay or at a timestamp; it returns awaiting_confirmation and a confirm_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 an approve_url that you open in the Plori web app.

  • Workflows: list_workflows (every workflow, or one agent's with agent_id, or the unassigned ones with agent_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 on base_version), set_workflow_agent (assign one of your agents to a workflow, typically after delete_agent reports paused workflows or run_workflow returns workflow_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-card

  • OAuth discovery: RFC 9728 protected-resource metadata on api.plori.ai, dynamic client registration supported

  • Registry entry: ai.plori/plori in 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

Available Tools

25 tools
answer_pending_inputAnswer pending questionA
Destructive
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
noteNoAn optional note recorded with the answer.
valueNoFor an input request: the value to supply.
run_idYesThe parked run's id.
approvedNoFor an approval request: set false to deny. Only the owner can approve in the Plori web app.
tool_call_idYesThe tool_call_id of the pending request (from list_pending_inputs).
max_turn_secondsNoOptional soft wall-clock budget to preserve on the continuation run; it does not change the parked run or impose a hard deadline.

Output Schema

ParametersJSON Schema
NameRequiredDescription
run_idNoThe continuation run created by the answer.
statusYesAnswer status.
alreadyNoWhether this request had already been answered.
session_idNoThe continuation run's session.
tool_call_idYesThe pending tool call that was answered.

TDQS

A4.7/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 runA
Destructive
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
run_idYesThe run id returned by invoke_agent.
agent_idYesThe agent's UUID.

Output Schema

ParametersJSON Schema
NameRequiredDescription
runIdYesThe run whose cancellation was requested.
statusYesCancellation request status.

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 agentA
Idempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesThe agent's name. Reusing a previous name returns that existing agent.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesThe Agent's unique identifier; pass it to other tools as agent_id.
urlNoThis Agent's page in the plori web app.
nameYesThe Agent's name, chosen by its owner and unique within the account.
modelYesThe 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.
configYesArbitrary JSON owned by the producing engine.
movingNoTrue while this Agent's files are being copied to a new disk; check storage_notice rather than a separate route for the outcome.
statusNoThe live warm-session state: warming, ready, or sleeping; empty when no session is active.
backendYesThe compute backend this Agent runs on.
user_idYesThe identifier of the account that owns this Agent.
deletingNoTrue while this Agent's disk is still being erased; offer no action on it besides retrying the deletion itself.
existingNoWhether create_agent returned an existing same-name agent instead of creating one.
queued_atNoWhen a still-warming attach was accepted; present only while it is queued for node capacity.
created_atYesWhen the Agent was created.
last_run_atNoWhen this Agent last started a run; absent when it has never run.
deleting_sinceNoWhen the deletion was first requested; present only while deleting is true.
storage_noticeNoThe one sentence, if any, telling the owner about a storage move that stopped; show it verbatim, not paraphrased.
effective_modelYesThe model a run on this Agent will actually use. plori-auto means the hosted router chooses per turn.
advisor_max_spend_micro_usdYesOptional maximum advisor-completion spend per turn in micro-US-dollars. Zero disables advisor completions; null leaves no spend cap.

TDQS

A4.5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesA short name for the workflow.
agent_idNoOptional 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_exprNoCron schedule (required when trigger_kind is "cron"), e.g. "0 9 * * *". A 5-field cron or an @daily/@hourly descriptor, evaluated in UTC.
descriptionNoOptional description of what the workflow does. It is prose for the reader; no field is derived from it.
trigger_kindNoOptional trigger: "manual" (default), "cron", or "webhook". The build can change it later: a schedule or webhook trigger step sets it.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
nameYes
engineYes
statusYes
user_idYes
agent_idYes
hook_keyYes
cron_exprYes
created_atYes
updated_atYes
descriptionYes
notify_prefYes
next_fire_atYes
trigger_kindYes
paused_reasonNo
template_slugNo
active_versionYes
current_versionYes
spend_cap_monthYes
agent_deleted_atNo

TDQS

A4.6/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 agentA
DestructiveIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
agent_idYesThe agent's UUID to delete.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesThe successful HTTP status code from the underlying operation.
workflows_pausedNoHow 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

A4.3/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 workflowA
DestructiveIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
opsYesOne or more edits applied atomically in order.
workflow_idYesThe workflow's UUID.
base_versionYesThe workflow's current_version; the edit conflicts if it changed.

Output Schema

ParametersJSON Schema
NameRequiredDescription
versionYesThe new draft version created by the edit.
resolvedNoExternal identifiers resolved while binding the edit.
projectionYesThe value-light projection of the edited workflow definition.
workflow_idYesThe edited workflow.

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 trashA
DestructiveIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
agent_idYesThe agent's UUID whose trash to empty.

Output Schema

ParametersJSON Schema
NameRequiredDescription
diskYesThe account's disk state right after emptying, the same shape get_disk returns.
bytes_freedYesBytes 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

A4.7/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 detailsA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
agent_idYesThe agent's UUID (from list_agents or create_agent).

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesThe Agent's unique identifier; pass it to other tools as agent_id.
urlNoThis Agent's page in the plori web app.
nameYesThe Agent's name, chosen by its owner and unique within the account.
modelYesThe 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.
configYesArbitrary JSON owned by the producing engine.
movingNoTrue while this Agent's files are being copied to a new disk; check storage_notice rather than a separate route for the outcome.
statusNoThe live warm-session state: warming, ready, or sleeping; empty when no session is active.
backendYesThe compute backend this Agent runs on.
mailboxYesThis agent's mailbox letters, open ones (accepted, delivering, blocked) first, then applied or undeliverable ones, newest within each group, at most 20.
user_idYesThe identifier of the account that owns this Agent.
deletingNoTrue while this Agent's disk is still being erased; offer no action on it besides retrying the deletion itself.
queued_atNoWhen a still-warming attach was accepted; present only while it is queued for node capacity.
created_atYesWhen the Agent was created.
last_run_atNoWhen this Agent last started a run; absent when it has never run.
deleting_sinceNoWhen the deletion was first requested; present only while deleting is true.
storage_noticeNoThe one sentence, if any, telling the owner about a storage move that stopped; show it verbatim, not paraphrased.
effective_modelYesThe model a run on this Agent will actually use. plori-auto means the hosted router chooses per turn.
advisor_max_spend_micro_usdYesOptional maximum advisor-completion spend per turn in micro-US-dollars. Zero disables advisor completions; null leaves no spend cap.

TDQS

A3.9/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 balanceA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
packsYesCredit 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.
plansYesSubscription plans on offer, with their monthly credit grant.
limitsYesThe caps this account's plan tier enforces.
balanceYesThe account's remaining prepaid balance, in credits. 1,000,000 credits = 1 US dollar.
user_idYesThe identifier of the account this balance belongs to.
audienceYes
plan_tierYesThe plan tier this account resolves to: free, pro or power. An account with no active plan is free.
active_planYesThe account's current subscription, or null when it has none and is on the free tier.
balance_usdYesThe account balance formatted in US dollars, without a currency symbol.
account_emailYesThe email address of the account this balance belongs to.
can_manage_billingYes
low_credit_thresholdYesThe balance, in the same credits, below which this account is warned it is running low.

TDQS

A4.7/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 usageA
Read-only
Inspect

Get the authenticated account's disk state (included, purchased, used bytes, and monthly cost).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
agentsNoThe 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_bytesYes
total_bytesYes
trash_bytesNo
usage_staleNoTrue 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_levelYes
included_bytesYes
monthly_creditsYes
purchased_bytesYes
usage_observed_atNoWhen 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_gbYes

TDQS

A3.5/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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 resultA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
waitNoWhen 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_idYesThe run id returned by invoke_agent.
agent_idYesThe agent's UUID.
wait_secondsNoOptional: how many seconds to wait when wait=true (maximum 1800). Omit to use the window your MCP client can hold.

Output Schema

ParametersJSON Schema
NameRequiredDescription
urlNoA deep link to this run's session in the plori web app.
hintNoWhat to do next with this run, in one sentence. Present only while the run is non-terminal.
textNoThe assistant's reply once the run has finished. While a run is still going this is the run's own status message, not an answer, and is often absent — read last_worklog and last_tool_step instead.
causeNoMachine-readable cause for a non-normal terminal state.
errorNoWhy a terminal error or cancelled run failed, whether it was charged and what to do about it. Absent for a run that is still going or that finished normally.
filesNoFiles 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_idYesThe public run identifier.
statusYesThe current run status.
tokensNoAttributed token count; null when attribution is unavailable.
advisorNoAdvisor calls used and allowed, spend this turn, and its optional spend cap in micro-US-dollars.
creditsNoAttributed spend in micro-US-dollars; null when attribution is unavailable.
ended_atNoWhen the run reached a terminal state.
retryableNoWhether 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_idYesThe durable conversation/session identifier.
started_atNoWhen the run started.
stop_reasonNoController-selected stop reason, when present.
input_statusNoThe durable status of this run's human-input request, when it has one: pending, answered, cancelled or expired. cancelled and expired are terminal — that run will never resume, so stop polling it.
last_worklogNoThe agent's most recent one-sentence note about what it is doing, from the run's durable event log. Absent for a terminal result and for a run that has written none.
input_expiredNoTrue 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_msNoLegacy spelling of poll_after_seconds in milliseconds; the two always agree. Prefer poll_after_seconds.
resume_run_idNoThe exact auto-resume successor for an interrupted run; poll this run next.
resume_statusNoAuto-resume disposition for an interrupted run: pending, resumed, failed, or unknown.
tool_progressNoDurable tool execution progress; absent when this run has no tool-progress telemetry.
usage_by_roleNoAttributed spend, tokens, and model-call counts split into executor, advisor, and reviewer roles.
last_tool_stepNoWhat this run last did with a tool: "running <tool>" while a call is in flight, otherwise "completed <tool>" for the most recent finished call. Absent for a terminal result and for a run with no tool-progress telemetry.
pending_inputsNoHuman inputs blocking an awaiting_input run.
elapsed_secondsNoSeconds since the run started; absent for a terminal result.
upstream_statusNoThe model provider's HTTP status when this run died on an upstream fault; absent otherwise.
last_activity_atNoWhen the run last wrote a note or finished a tool call. Absent for a terminal result and for a run that has done neither.
last_heartbeat_atNoMost recent durable executor heartbeat.
poll_after_secondsNoSuggested seconds before polling again, paced to this run's recent tool-completion rate; absent for a terminal result.
continuation_run_idNoThe exact continuation created for an answered input; poll this run next.

TDQS

A4.4/5.0
Behavior5/5

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.

Conciseness3/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 usageA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
toolsYes
agentsYes
totalsYes
by_kindYes
by_roleYes
workflowsYes
recent_runsYes
workflow_executionsYes

TDQS

A4.4/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 workflowA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
workflow_idYesThe workflow's UUID (from list_workflows or create_workflow).

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
nameYes
engineYes
statusYes
user_idYes
agent_idYes
hook_keyYes
cron_exprYes
created_atYes
projectionYesArbitrary JSON owned by the producing engine.
updated_atYes
descriptionYes
notify_prefYes
next_fire_atYes
trigger_kindYes
paused_reasonNo
template_slugNo
active_versionYes
current_versionYes
spend_cap_monthYes
agent_deleted_atNo

TDQS

A3.6/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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 executionA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
workflow_idYesThe workflow's UUID.
execution_idYesThe execution's UUID (from run_workflow).

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
errorNoArbitrary JSON owned by the producing engine.
faultYesWhy 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.
stepsNoArbitrary JSON owned by the producing engine.
billedYesThe billing flag. True only for a user-fault succeeded, failed, or timed-out execution.
statusYes
creditsYes
ended_atYes
created_atYes
started_atYes
step_statsNoArbitrary JSON owned by the producing engine.
duration_msYes
workflow_idYes
trigger_sourceYes

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 versionA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
versionYesThe positive version number to retrieve.
workflow_idYesThe workflow's UUID.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
authorYes
versionYes
created_atYes
definitionNoArbitrary JSON owned by the producing engine.
projectionNoArbitrary JSON owned by the producing engine.
chat_run_idYes
workflow_idYes

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 agentA
Destructive
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
waitNoWait 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.
messageYesThe message to send to the agent.
agent_idYesThe agent's UUID.
session_idNoOptional 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_urlNoOptional callback URL for this run. Must use http or https and resolve only to public addresses.
wait_secondsNoOptional: 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_secretNoOptional secret used to sign callback deliveries with HMAC-SHA256.
idempotency_keyNoOptional 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_tokensNoOptional 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_secondsNoOptional 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_usdNoOptional 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

ParametersJSON Schema
NameRequiredDescription
urlNoA deep link to this run's session in the plori web app.
hintNoWhat to do next with this run, in one sentence. Present only while the run is non-terminal.
textNoThe assistant's reply once the run has finished. While a run is still going this is the run's own status message, not an answer, and is often absent — read last_worklog and last_tool_step instead.
causeNoMachine-readable cause for a non-normal terminal state.
errorNoWhy a terminal error or cancelled run failed, whether it was charged and what to do about it. Absent for a run that is still going or that finished normally.
filesNoFiles 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_idYesThe public run identifier.
statusYesThe current run status.
tokensNoAttributed token count; null when attribution is unavailable.
advisorNoAdvisor calls used and allowed, spend this turn, and its optional spend cap in micro-US-dollars.
creditsNoAttributed spend in micro-US-dollars; null when attribution is unavailable.
ended_atNoWhen the run reached a terminal state.
retryableNoWhether 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_idYesThe durable conversation/session identifier.
started_atNoWhen the run started.
stop_reasonNoController-selected stop reason, when present.
input_statusNoThe durable status of this run's human-input request, when it has one: pending, answered, cancelled or expired. cancelled and expired are terminal — that run will never resume, so stop polling it.
last_worklogNoThe agent's most recent one-sentence note about what it is doing, from the run's durable event log. Absent for a terminal result and for a run that has written none.
input_expiredNoTrue 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_msNoLegacy spelling of poll_after_seconds in milliseconds; the two always agree. Prefer poll_after_seconds.
resume_run_idNoThe exact auto-resume successor for an interrupted run; poll this run next.
resume_statusNoAuto-resume disposition for an interrupted run: pending, resumed, failed, or unknown.
tool_progressNoDurable tool execution progress; absent when this run has no tool-progress telemetry.
usage_by_roleNoAttributed spend, tokens, and model-call counts split into executor, advisor, and reviewer roles.
last_tool_stepNoWhat this run last did with a tool: "running <tool>" while a call is in flight, otherwise "completed <tool>" for the most recent finished call. Absent for a terminal result and for a run with no tool-progress telemetry.
pending_inputsNoHuman inputs blocking an awaiting_input run.
elapsed_secondsNoSeconds since the run started; absent for a terminal result.
upstream_statusNoThe model provider's HTTP status when this run died on an upstream fault; absent otherwise.
last_activity_atNoWhen the run last wrote a note or finished a tool call. Absent for a terminal result and for a run that has done neither.
last_heartbeat_atNoMost recent durable executor heartbeat.
poll_after_secondsNoSuggested seconds before polling again, paced to this run's recent tool-completion rate; absent for a terminal result.
continuation_run_idNoThe exact continuation created for an answered input; poll this run next.

TDQS

A4.6/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 agentsA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
itemsYesThe returned items, in the endpoint's documented order.

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 connectionsA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
connectionsYesThird-party OAuth connection status records; never secret material.

TDQS

A4.4/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 questionsA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
agent_idYesThe agent's UUID.

Output Schema

ParametersJSON Schema
NameRequiredDescription
pending_inputsYesRuns 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

A4.2/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 runsA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoHow many runs to return, newest first (default 20, maximum 100).
cursorNoThe next_cursor from a previous list_runs result, to continue where it stopped. Omit for the newest page.
agent_idYesThe agent's UUID.

Output Schema

ParametersJSON Schema
NameRequiredDescription
itemsYesOne page of the agent's runs, most recently started first.
next_cursorNoPass this back as cursor to read the next page. Absent when this page is the end of the history.

TDQS

A4.6/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 executionsB
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
workflow_idYesThe workflow's UUID (from list_workflows or create_workflow).

Output Schema

ParametersJSON Schema
NameRequiredDescription
executionsYesRecent workflow executions, most recent first.

TDQS

B3.2/5.0
Behavior3/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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 workflowsA
Read-only
Inspect

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).

ParametersJSON Schema
NameRequiredDescriptionDefault
agent_idNoOptional: a UUID of one of your agents to list only its workflows, or "none" for the unassigned ones.

Output Schema

ParametersJSON Schema
NameRequiredDescription
workflowsYesWorkflows visible to the authenticated account and optional agent filter.

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 workflowA
Destructive
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
workflow_idYesThe workflow's UUID (from list_workflows or create_workflow).
trigger_payloadNoOptional sample input to hand the trigger (useful for a webhook workflow: run it with a sample body).

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
errorNoArbitrary JSON owned by the producing engine.
faultYesWhy 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.
stepsNoArbitrary JSON owned by the producing engine.
billedYesThe billing flag. True only for a user-fault succeeded, failed, or timed-out execution.
statusYes
creditsYes
ended_atYes
created_atYes
started_atYes
step_statsNoArbitrary JSON owned by the producing engine.
duration_msYes
workflow_idYes
trigger_sourceYes

TDQS

A4.5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 runA
Destructive
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
promptYesThe message to send the agent when the schedule fires.
fire_atNoFire at this RFC3339 timestamp (mutually exclusive with delay_seconds).
agent_idYesThe agent's UUID.
session_idNoOptional thread/session id to deliver the scheduled run into.
delay_secondsNoFire this many seconds from now (mutually exclusive with fire_at).

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
kindYes
promptYes
statusYes
fire_atNo
agent_idYes
attemptsYes
metadataNoArbitrary JSON owned by the producing engine.
thread_idNo
created_atYes
last_errorNo
confirm_urlNo
confirmed_atNo
last_fired_atNo

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 agentA
DestructiveIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
agent_idYesThe UUID of one of your agents to assign.
workflow_idYesThe workflow's UUID.
base_versionNoOptional workflow current_version to compare before assignment. Omit it to use the current version.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesA short confirmation of the assignment.
versionYesThe workflow current_version checked for this assignment.
agent_idYesThe account-owned agent assigned to the workflow.
workflow_idYesThe workflow whose agent changed.
agent_deleted_atYesAlways null after assigning an agent: the workflow is no longer marked agentless.

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines5/5

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.

  1. 7 tool updatesv0.17.0
    • Changedanswer_pending_input3 fields changed
      • removedInput schema / properties / always_allow
        Removed 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"
        -}
      • changedInput schema / properties / approved / description
        Previous 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."
      • removedInput schema / properties / scope
        Removed 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"
        -}
    • Changedempty_trash1 field changed
      • addedOutput schema / properties / disk / properties / agents
        Added 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"
        +  ]
        +}
    • Changedget_disk1 field changed
      • addedOutput schema / properties / agents
        Added 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"
        +  ]
        +}
    • Changedget_run_result1 field changed
      • addedOutput schema / properties / pending_inputs / items / properties / approve_url
        Added value: +{
        +  "type": "string"
        +}
    • Changedinvoke_agent1 field changed
      • addedOutput schema / properties / pending_inputs / items / properties / approve_url
        Added value: +{
        +  "type": "string"
        +}
    • Changedlist_pending_inputs1 field changed
      • addedOutput schema / properties / pending_inputs / items / properties / approve_url
        Added value: +{
        +  "type": "string"
        +}
    • Changedschedule_run2 fields changed
      • addedOutput schema / properties / confirm_url
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / confirmed_at
        Added value: +{
        +  "type": [
        +    "null",
        +    "string"
        +  ]
        +}
  2. 7 tool updatesv0.16.2
    • Changedcreate_agent2 fields changed
      • addedOutput schema / properties / advisor_max_spend_micro_usd
        Added 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"
        +  ]
        +}
      • changedOutput schema / required
        Previous 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"
        +]
    • Changedget_agent2 fields changed
      • addedOutput schema / properties / advisor_max_spend_micro_usd
        Added 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"
        +  ]
        +}
      • changedOutput schema / required
        Previous 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"
        +]
    • Changedget_run_result3 fields changed
      • addedOutput schema / properties / advisor
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Advisor calls used and allowed, spend this turn, and its optional spend cap in micro-US-dollars.",
        +  "properties": {
        +    "calls_allowed": {
        +      "type": "integer"
        +    },
        +    "calls_used": {
        +      "type": "integer"
        +    },
        +    "spend_cap_micro_usd": {
        +      "type": [
        +        "null",
        +        "integer"
        +      ]
        +    },
        +    "spend_micro_usd": {
        +      "description": "Gross advisor consumption for the turn; the cap compares against this amount.",
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "calls_used",
        +    "calls_allowed",
        +    "spend_micro_usd"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / error / properties / upgrade
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Which plan lifts the limit this run ended at, when it ended at one.",
        +  "properties": {
        +    "anonymous": {
        +      "type": "boolean"
        +    },
        +    "limit": {
        +      "type": "string"
        +    },
        +    "message": {
        +      "type": "string"
        +    },
        +    "offer": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "discount_code": {
        +          "type": "string"
        +        },
        +        "first_period_price_micro_usd": {
        +          "type": "integer"
        +        },
        +        "message": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "discount_code",
        +        "first_period_price_micro_usd",
        +        "message"
        +      ],
        +      "type": [
        +        "null",
        +        "object"
        +      ]
        +    },
        +    "plan": {
        +      "type": "string"
        +    },
        +    "remedies": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "kind": {
        +            "type": "string"
        +          },
        +          "limits": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "disk_gb": {
        +                "type": "integer"
        +              },
        +              "max_active_workflows": {
        +                "type": "integer"
        +              },
        +              "max_agents": {
        +                "type": "integer"
        +              },
        +              "max_concurrent_runs": {
        +                "type": "integer"
        +              }
        +            },
        +            "required": [
        +              "max_concurrent_runs",
        +              "max_agents",
        +              "max_active_workflows",
        +              "disk_gb"
        +            ],
        +            "type": [
        +              "null",
        +              "object"
        +            ]
        +          },
        +          "message": {
        +            "type": "string"
        +          },
        +          "offer": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "discount_code": {
        +                "type": "string"
        +              },
        +              "first_period_price_micro_usd": {
        +                "type": "integer"
        +              },
        +              "message": {
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "discount_code",
        +              "first_period_price_micro_usd",
        +              "message"
        +            ],
        +            "type": [
        +              "null",
        +              "object"
        +            ]
        +          },
        +          "plan": {
        +            "type": "string"
        +          },
        +          "url": {
        +            "type": "string"
        +          },
        +          "usd_cents_per_month": {
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "kind",
        +          "message"
        +        ],
        +        "type": "object"
        +      },
        +      "type": [
        +        "null",
        +        "array"
        +      ]
        +    },
        +    "url": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "limit",
        +    "plan",
        +    "message",
        +    "remedies"
        +  ],
        +  "type": [
        +    "null",
        +    "object"
        +  ]
        +}
      • addedOutput schema / properties / usage_by_role
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Attributed spend, tokens, and model-call counts split into executor, advisor, and reviewer roles.",
        +  "properties": {
        +    "advisor": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "calls": {
        +          "type": "integer"
        +        },
        +        "credits": {
        +          "type": "integer"
        +        },
        +        "tokens": {
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "credits",
        +        "tokens",
        +        "calls"
        +      ],
        +      "type": "object"
        +    },
        +    "executor": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "calls": {
        +          "type": "integer"
        +        },
        +        "credits": {
        +          "type": "integer"
        +        },
        +        "tokens": {
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "credits",
        +        "tokens",
        +        "calls"
        +      ],
        +      "type": "object"
        +    },
        +    "reviewer": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "calls": {
        +          "type": "integer"
        +        },
        +        "credits": {
        +          "type": "integer"
        +        },
        +        "tokens": {
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "credits",
        +        "tokens",
        +        "calls"
        +      ],
        +      "type": "object"
        +    }
        +  },
        +  "required": [
        +    "executor",
        +    "advisor",
        +    "reviewer"
        +  ],
        +  "type": [
        +    "null",
        +    "object"
        +  ]
        +}
    • Changedget_usage11 fields changed
      • addedOutput schema / properties / by_role
        Added 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"
        +}
      • addedOutput schema / properties / recent_runs / items / properties / advisor
        Added 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"
        +}
      • addedOutput schema / properties / recent_runs / items / properties / credits / description
        Added value: +"The net charge after any refund."
      • addedOutput schema / properties / recent_runs / items / properties / error / properties / upgrade
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Which plan lifts the limit this run ended at, when it ended at one.",
        +  "properties": {
        +    "anonymous": {
        +      "type": "boolean"
        +    },
        +    "limit": {
        +      "type": "string"
        +    },
        +    "message": {
        +      "type": "string"
        +    },
        +    "offer": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "discount_code": {
        +          "type": "string"
        +        },
        +        "first_period_price_micro_usd": {
        +          "type": "integer"
        +        },
        +        "message": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "discount_code",
        +        "first_period_price_micro_usd",
        +        "message"
        +      ],
        +      "type": [
        +        "null",
        +        "object"
        +      ]
        +    },
        +    "plan": {
        +      "type": "string"
        +    },
        +    "remedies": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "kind": {
        +            "type": "string"
        +          },
        +          "limits": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "disk_gb": {
        +                "type": "integer"
        +              },
        +              "max_active_workflows": {
        +                "type": "integer"
        +              },
        +              "max_agents": {
        +                "type": "integer"
        +              },
        +              "max_concurrent_runs": {
        +                "type": "integer"
        +              }
        +            },
        +            "required": [
        +              "max_concurrent_runs",
        +              "max_agents",
        +              "max_active_workflows",
        +              "disk_gb"
        +            ],
        +            "type": [
        +              "null",
        +              "object"
        +            ]
        +          },
        +          "message": {
        +            "type": "string"
        +          },
        +          "offer": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "discount_code": {
        +                "type": "string"
        +              },
        +              "first_period_price_micro_usd": {
        +                "type": "integer"
        +              },
        +              "message": {
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "discount_code",
        +              "first_period_price_micro_usd",
        +              "message"
        +            ],
        +            "type": [
        +              "null",
        +              "object"
        +            ]
        +          },
        +          "plan": {
        +            "type": "string"
        +          },
        +          "url": {
        +            "type": "string"
        +          },
        +          "usd_cents_per_month": {
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "kind",
        +          "message"
        +        ],
        +        "type": "object"
        +      },
        +      "type": [
        +        "null",
        +        "array"
        +      ]
        +    },
        +    "url": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "limit",
        +    "plan",
        +    "message",
        +    "remedies"
        +  ],
        +  "type": [
        +    "null",
        +    "object"
        +  ]
        +}
      • addedOutput schema / properties / recent_runs / items / properties / gross_micro_usd
        Added value: +{
        +  "description": "Gross consumption before any refund.",
        +  "type": "integer"
        +}
      • addedOutput schema / properties / recent_runs / items / properties / refund_reason
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / recent_runs / items / properties / refund_withheld_reason
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / recent_runs / items / properties / refunded_micro_usd
        Added value: +{
        +  "description": "The refund reported once for this run.",
        +  "type": "integer"
        +}
      • addedOutput schema / properties / recent_runs / items / properties / usage_by_role
        Added 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"
        +  ]
        +}
      • changedOutput schema / properties / recent_runs / items / required
        Previous 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"
        +]
      • changedOutput schema / required
        Previous 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"
        +]
    • Changedinvoke_agent4 fields changed
      • addedInput schema / properties / max_advisor_spend_micro_usd
        Added 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"
        +}
      • addedOutput schema / properties / advisor
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Advisor calls used and allowed, spend this turn, and its optional spend cap in micro-US-dollars.",
        +  "properties": {
        +    "calls_allowed": {
        +      "type": "integer"
        +    },
        +    "calls_used": {
        +      "type": "integer"
        +    },
        +    "spend_cap_micro_usd": {
        +      "type": [
        +        "null",
        +        "integer"
        +      ]
        +    },
        +    "spend_micro_usd": {
        +      "description": "Gross advisor consumption for the turn; the cap compares against this amount.",
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "calls_used",
        +    "calls_allowed",
        +    "spend_micro_usd"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / error / properties / upgrade
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Which plan lifts the limit this run ended at, when it ended at one.",
        +  "properties": {
        +    "anonymous": {
        +      "type": "boolean"
        +    },
        +    "limit": {
        +      "type": "string"
        +    },
        +    "message": {
        +      "type": "string"
        +    },
        +    "offer": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "discount_code": {
        +          "type": "string"
        +        },
        +        "first_period_price_micro_usd": {
        +          "type": "integer"
        +        },
        +        "message": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "discount_code",
        +        "first_period_price_micro_usd",
        +        "message"
        +      ],
        +      "type": [
        +        "null",
        +        "object"
        +      ]
        +    },
        +    "plan": {
        +      "type": "string"
        +    },
        +    "remedies": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "kind": {
        +            "type": "string"
        +          },
        +          "limits": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "disk_gb": {
        +                "type": "integer"
        +              },
        +              "max_active_workflows": {
        +                "type": "integer"
        +              },
        +              "max_agents": {
        +                "type": "integer"
        +              },
        +              "max_concurrent_runs": {
        +                "type": "integer"
        +              }
        +            },
        +            "required": [
        +              "max_concurrent_runs",
        +              "max_agents",
        +              "max_active_workflows",
        +              "disk_gb"
        +            ],
        +            "type": [
        +              "null",
        +              "object"
        +            ]
        +          },
        +          "message": {
        +            "type": "string"
        +          },
        +          "offer": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "discount_code": {
        +                "type": "string"
        +              },
        +              "first_period_price_micro_usd": {
        +                "type": "integer"
        +              },
        +              "message": {
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "discount_code",
        +              "first_period_price_micro_usd",
        +              "message"
        +            ],
        +            "type": [
        +              "null",
        +              "object"
        +            ]
        +          },
        +          "plan": {
        +            "type": "string"
        +          },
        +          "url": {
        +            "type": "string"
        +          },
        +          "usd_cents_per_month": {
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "kind",
        +          "message"
        +        ],
        +        "type": "object"
        +      },
        +      "type": [
        +        "null",
        +        "array"
        +      ]
        +    },
        +    "url": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "limit",
        +    "plan",
        +    "message",
        +    "remedies"
        +  ],
        +  "type": [
        +    "null",
        +    "object"
        +  ]
        +}
      • addedOutput schema / properties / usage_by_role
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Attributed spend, tokens, and model-call counts split into executor, advisor, and reviewer roles.",
        +  "properties": {
        +    "advisor": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "calls": {
        +          "type": "integer"
        +        },
        +        "credits": {
        +          "type": "integer"
        +        },
        +        "tokens": {
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "credits",
        +        "tokens",
        +        "calls"
        +      ],
        +      "type": "object"
        +    },
        +    "executor": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "calls": {
        +          "type": "integer"
        +        },
        +        "credits": {
        +          "type": "integer"
        +        },
        +        "tokens": {
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "credits",
        +        "tokens",
        +        "calls"
        +      ],
        +      "type": "object"
        +    },
        +    "reviewer": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "calls": {
        +          "type": "integer"
        +        },
        +        "credits": {
        +          "type": "integer"
        +        },
        +        "tokens": {
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "credits",
        +        "tokens",
        +        "calls"
        +      ],
        +      "type": "object"
        +    }
        +  },
        +  "required": [
        +    "executor",
        +    "advisor",
        +    "reviewer"
        +  ],
        +  "type": [
        +    "null",
        +    "object"
        +  ]
        +}
    • Changedlist_agents2 fields changed
      • addedOutput schema / properties / items / items / properties / advisor_max_spend_micro_usd
        Added 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"
        +  ]
        +}
      • changedOutput schema / properties / items / items / required
        Previous 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"
        +]
    • Changedlist_runs9 fields changed
      • addedOutput schema / properties / items / items / properties / advisor
        Added 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"
        +}
      • addedOutput schema / properties / items / items / properties / credits / description
        Added value: +"The net charge after any refund."
      • addedOutput schema / properties / items / items / properties / error / properties / upgrade
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Which plan lifts the limit this run ended at, when it ended at one.",
        +  "properties": {
        +    "anonymous": {
        +      "type": "boolean"
        +    },
        +    "limit": {
        +      "type": "string"
        +    },
        +    "message": {
        +      "type": "string"
        +    },
        +    "offer": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "discount_code": {
        +          "type": "string"
        +        },
        +        "first_period_price_micro_usd": {
        +          "type": "integer"
        +        },
        +        "message": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "discount_code",
        +        "first_period_price_micro_usd",
        +        "message"
        +      ],
        +      "type": [
        +        "null",
        +        "object"
        +      ]
        +    },
        +    "plan": {
        +      "type": "string"
        +    },
        +    "remedies": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "kind": {
        +            "type": "string"
        +          },
        +          "limits": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "disk_gb": {
        +                "type": "integer"
        +              },
        +              "max_active_workflows": {
        +                "type": "integer"
        +              },
        +              "max_agents": {
        +                "type": "integer"
        +              },
        +              "max_concurrent_runs": {
        +                "type": "integer"
        +              }
        +            },
        +            "required": [
        +              "max_concurrent_runs",
        +              "max_agents",
        +              "max_active_workflows",
        +              "disk_gb"
        +            ],
        +            "type": [
        +              "null",
        +              "object"
        +            ]
        +          },
        +          "message": {
        +            "type": "string"
        +          },
        +          "offer": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "discount_code": {
        +                "type": "string"
        +              },
        +              "first_period_price_micro_usd": {
        +                "type": "integer"
        +              },
        +              "message": {
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "discount_code",
        +              "first_period_price_micro_usd",
        +              "message"
        +            ],
        +            "type": [
        +              "null",
        +              "object"
        +            ]
        +          },
        +          "plan": {
        +            "type": "string"
        +          },
        +          "url": {
        +            "type": "string"
        +          },
        +          "usd_cents_per_month": {
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "kind",
        +          "message"
        +        ],
        +        "type": "object"
        +      },
        +      "type": [
        +        "null",
        +        "array"
        +      ]
        +    },
        +    "url": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "limit",
        +    "plan",
        +    "message",
        +    "remedies"
        +  ],
        +  "type": [
        +    "null",
        +    "object"
        +  ]
        +}
      • addedOutput schema / properties / items / items / properties / gross_micro_usd
        Added value: +{
        +  "description": "Gross consumption before any refund.",
        +  "type": "integer"
        +}
      • addedOutput schema / properties / items / items / properties / refund_reason
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / items / items / properties / refund_withheld_reason
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / items / items / properties / refunded_micro_usd
        Added value: +{
        +  "description": "The refund reported once for this run.",
        +  "type": "integer"
        +}
      • addedOutput schema / properties / items / items / properties / usage_by_role
        Added 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"
        +  ]
        +}
      • changedOutput schema / properties / items / items / required
        Previous 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"
        +]
  3. 26 tool updatesv0.16.0
    • Changedanswer_pending_input2 fields changed
      • addedInput schema / properties / scope
        Added 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"
        +}
      • changedOutput 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"
        +}
    • Changedcancel_run1 field changed
      • changedOutput 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"
        +}
    • Changedcreate_agent2 fields changed
      • removedInput schema / properties / model
        Removed 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"
        -}
      • changedOutput 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"
        +}
    • Changedcreate_workflow4 fields changed
      • changedInput schema / properties / cron_expr / description
        Previous 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."
      • changedInput schema / properties / description / description
        Previous 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."
      • changedInput schema / properties / trigger_kind / description
        Previous 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."
      • changedOutput 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"
        +}
    • Changeddelete_agent1 field changed
      • changedOutput 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"
        +}
    • Changededit_workflow1 field changed
      • changedOutput 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"
        +}
    • Addedempty_trash
    • Changedget_agent1 field changed
      • changedOutput 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"
        +}
    • Changedget_credits1 field changed
      • changedOutput 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"
        +}
    • Changedget_disk1 field changed
      • changedOutput 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"
        +}
    • Changedget_run_result3 fields changed
      • addedInput schema / properties / wait
        Added value: +{
        +  "description": "When true, wait for a terminal result or human input (see this tool's description for how long the hold lasts). After this tool returns, continue polling while status is non-terminal; it cannot wake an idle client.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / wait_seconds
        Added value: +{
        +  "description": "Optional: how many seconds to wait when wait=true (maximum 1800). Omit to use the window your MCP client can hold.",
        +  "maximum": 1800,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "cause": {
        +      "description": "Machine-readable cause for a non-normal terminal state.",
        +      "type": "string"
        +    },
        +    "continuation_run_id": {
        +      "description": "The exact continuation created for an answered input; poll this run next.",
        +      "type": "string"
        +    },
        +    "credits": {
        +      "description": "Attributed spend in micro-US-dollars; null when attribution is unavailable.",
        +      "type": [
        +        "null",
        +        "integer"
        +      ]
        +    },
        +    "elapsed_seconds": {
        +      "description": "Seconds since the run started; absent for a terminal result.",
        +      "type": "integer"
        +    },
        +    "ended_at": {
        +      "description": "When the run reached a terminal state.",
        +      "type": [
        +        "null",
        +        "string"
        +      ]
        +    },
        +    "error": {
        +      "additionalProperties": false,
        +      "description": "Why a terminal error or cancelled run failed, whether it was charged and what to do about it. Absent for a run that is still going or that finished normally.",
        +      "properties": {
        +        "class": {
        +          "description": "The failure class: the run's terminal cause, or \"unknown\" when none was recorded.",
        +          "type": "string"
        +        },
        +        "message": {
        +          "description": "What happened, and whether the work was charged.",
        +          "type": "string"
        +        },
        +        "next_step": {
        +          "description": "What to do about it.",
        +          "type": "string"
        +        },
        +        "retryable": {
        +          "description": "Whether sending the same message again could plausibly succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "required": [
        +        "class",
        +        "message",
        +        "retryable",
        +        "next_step"
        +      ],
        +      "type": [
        +        "null",
        +        "object"
        +      ]
        +    },
        +    "files": {
        +      "description": "Files on the agent's disk that this reply linked, in the order they appear. Each url is fetchable with the bearer token you called this tool with. Absent when the reply linked none.",
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "path": {
        +            "description": "The file's path on the agent's disk, rooted at the disk root.",
        +            "type": "string"
        +          },
        +          "url": {
        +            "description": "An absolute URL that streams the file's bytes, text or binary and of any size, with its own content type. Fetch it with the same bearer token you called this tool with.",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "path",
        +          "url"
        +        ],
        +        "type": "object"
        +      },
        +      "type": [
        +        "null",
        +        "array"
        +      ]
        +    },
        +    "hint": {
        +      "description": "What to do next with this run, in one sentence. Present only while the run is non-terminal.",
        +      "type": "string"
        +    },
        +    "input_expired": {
        +      "description": "True when this run is parked on a question its session has already moved past: a later run in the same conversation has completed. Do not answer it; start a new run instead.",
        +      "type": "boolean"
        +    },
        +    "input_status": {
        +      "description": "The durable status of this run's human-input request, when it has one: pending, answered, cancelled or expired. cancelled and expired are terminal — that run will never resume, so stop polling it.",
        +      "type": "string"
        +    },
        +    "last_activity_at": {
        +      "description": "When the run last wrote a note or finished a tool call. Absent for a terminal result and for a run that has done neither.",
        +      "type": [
        +        "null",
        +        "string"
        +      ]
        +    },
        +    "last_heartbeat_at": {
        +      "description": "Most recent durable executor heartbeat.",
        +      "type": [
        +        "null",
        +        "string"
        +      ]
        +    },
        +    "last_tool_step": {
        +      "description": "What this run last did with a tool: \"running <tool>\" while a call is in flight, otherwise \"completed <tool>\" for the most recent finished call. Absent for a terminal result and for a run with no tool-progress telemetry.",
        +      "type": "string"
        +    },
        +    "last_worklog": {
        +      "description": "The agent's most recent one-sentence note about what it is doing, from the run's durable event log. Absent for a terminal result and for a run that has written none.",
        +      "type": "string"
        +    },
        +    "pending_inputs": {
        +      "description": "Human inputs blocking an awaiting_input run.",
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "consent_tool": {
        +            "type": "string"
        +          },
        +          "kind": {
        +            "type": "string"
        +          },
        +          "prompt": {
        +            "type": "string"
        +          },
        +          "risk": {
        +            "type": "string"
        +          },
        +          "tool_call_id": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "tool_call_id",
        +          "kind",
        +          "prompt"
        +        ],
        +        "type": "object"
        +      },
        +      "type": [
        +        "null",
        +        "array"
        +      ]
        +    },
        +    "poll_after_ms": {
        +      "description": "Legacy spelling of poll_after_seconds in milliseconds; the two always agree. Prefer poll_after_seconds.",
        +      "type": "integer"
        +    },
        +    "poll_after_seconds": {
        +      "description": "Suggested seconds before polling again, paced to this run's recent tool-completion rate; absent for a terminal result.",
        +      "type": "integer"
        +    },
        +    "resume_run_id": {
        +      "description": "The exact auto-resume successor for an interrupted run; poll this run next.",
        +      "type": "string"
        +    },
        +    "resume_status": {
        +      "description": "Auto-resume disposition for an interrupted run: pending, resumed, failed, or unknown.",
        +      "type": "string"
        +    },
        +    "retryable": {
        +      "description": "Whether sending the same message again could plausibly succeed. False for a cause the same request would hit again, including time_limit — split the work or raise max_turn_seconds instead of retrying it unchanged.",
        +      "type": [
        +        "null",
        +        "boolean"
        +      ]
        +    },
        +    "run_id": {
        +      "description": "The public run identifier.",
        +      "type": "string"
        +    },
        +    "session_id": {
        +      "description": "The durable conversation/session identifier.",
        +      "type": "string"
        +    },
        +    "started_at": {
        +      "description": "When the run started.",
        +      "type": [
        +        "null",
        +        "string"
        +      ]
        +    },
        +    "status": {
        +      "description": "The current run status.",
        +      "type": "string"
        +    },
        +    "stop_reason": {
        +      "description": "Controller-selected stop reason, when present.",
        +      "type": "string"
        +    },
        +    "text": {
        +      "description": "The assistant's reply once the run has finished. While a run is still going this is the run's own status message, not an answer, and is often absent — read last_worklog and last_tool_step instead.",
        +      "type": "string"
        +    },
        +    "tokens": {
        +      "description": "Attributed token count; null when attribution is unavailable.",
        +      "type": [
        +        "null",
        +        "integer"
        +      ]
        +    },
        +    "tool_progress": {
        +      "additionalProperties": false,
        +      "description": "Durable tool execution progress; absent when this run has no tool-progress telemetry.",
        +      "properties": {
        +        "active_tools": {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "id": {
        +                "type": "string"
        +              },
        +              "name": {
        +                "type": "string"
        +              },
        +              "started_at": {
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "id",
        +              "name",
        +              "started_at"
        +            ],
        +            "type": "object"
        +          },
        +          "type": [
        +            "null",
        +            "array"
        +          ]
        +        },
        +        "completed_count": {
        +          "type": "integer"
        +        },
        +        "last_completed_at": {
        +          "type": [
        +            "null",
        +            "string"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "active_tools",
        +        "completed_count"
        +      ],
        +      "type": [
        +        "null",
        +        "object"
        +      ]
        +    },
        +    "upstream_status": {
        +      "description": "The model provider's HTTP status when this run died on an upstream fault; absent otherwise.",
        +      "type": "integer"
        +    },
        +    "url": {
        +      "description": "A deep link to this run's session in the plori web app.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "run_id",
        +    "session_id",
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedget_usage1 field changed
      • changedOutput 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"
        +}
    • Changedget_workflow1 field changed
      • changedOutput 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"
        +}
    • Changedget_workflow_execution1 field changed
      • changedOutput 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"
        +}
    • Changedget_workflow_version1 field changed
      • changedOutput 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"
        +}
    • Changedinvoke_agent7 fields changed
      • addedInput schema / properties / callback_secret
        Added value: +{
        +  "description": "Optional secret used to sign callback deliveries with HMAC-SHA256.",
        +  "type": "string"
        +}
      • addedInput schema / properties / callback_url
        Added value: +{
        +  "description": "Optional callback URL for this run. Must use http or https and resolve only to public addresses.",
        +  "type": "string"
        +}
      • changedInput schema / properties / max_turn_seconds / description
        Previous 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."
      • changedInput schema / properties / max_turn_tokens / description
        Previous 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."
      • changedInput schema / properties / wait / description
        Previous 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."
      • addedInput schema / properties / wait_seconds
        Added 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"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "cause": {
        +      "description": "Machine-readable cause for a non-normal terminal state.",
        +      "type": "string"
        +    },
        +    "continuation_run_id": {
        +      "description": "The exact continuation created for an answered input; poll this run next.",
        +      "type": "string"
        +    },
        +    "credits": {
        +      "description": "Attributed spend in micro-US-dollars; null when attribution is unavailable.",
        +      "type": [
        +        "null",
        +        "integer"
        +      ]
        +    },
        +    "elapsed_seconds": {
        +      "description": "Seconds since the run started; absent for a terminal result.",
        +      "type": "integer"
        +    },
        +    "ended_at": {
        +      "description": "When the run reached a terminal state.",
        +      "type": [
        +        "null",
        +        "string"
        +      ]
        +    },
        +    "error": {
        +      "additionalProperties": false,
        +      "description": "Why a terminal error or cancelled run failed, whether it was charged and what to do about it. Absent for a run that is still going or that finished normally.",
        +      "properties": {
        +        "class": {
        +          "description": "The failure class: the run's terminal cause, or \"unknown\" when none was recorded.",
        +          "type": "string"
        +        },
        +        "message": {
        +          "description": "What happened, and whether the work was charged.",
        +          "type": "string"
        +        },
        +        "next_step": {
        +          "description": "What to do about it.",
        +          "type": "string"
        +        },
        +        "retryable": {
        +          "description": "Whether sending the same message again could plausibly succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "required": [
        +        "class",
        +        "message",
        +        "retryable",
        +        "next_step"
        +      ],
        +      "type": [
        +        "null",
        +        "object"
        +      ]
        +    },
        +    "files": {
        +      "description": "Files on the agent's disk that this reply linked, in the order they appear. Each url is fetchable with the bearer token you called this tool with. Absent when the reply linked none.",
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "path": {
        +            "description": "The file's path on the agent's disk, rooted at the disk root.",
        +            "type": "string"
        +          },
        +          "url": {
        +            "description": "An absolute URL that streams the file's bytes, text or binary and of any size, with its own content type. Fetch it with the same bearer token you called this tool with.",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "path",
        +          "url"
        +        ],
        +        "type": "object"
        +      },
        +      "type": [
        +        "null",
        +        "array"
        +      ]
        +    },
        +    "hint": {
        +      "description": "What to do next with this run, in one sentence. Present only while the run is non-terminal.",
        +      "type": "string"
        +    },
        +    "input_expired": {
        +      "description": "True when this run is parked on a question its session has already moved past: a later run in the same conversation has completed. Do not answer it; start a new run instead.",
        +      "type": "boolean"
        +    },
        +    "input_status": {
        +      "description": "The durable status of this run's human-input request, when it has one: pending, answered, cancelled or expired. cancelled and expired are terminal — that run will never resume, so stop polling it.",
        +      "type": "string"
        +    },
        +    "last_activity_at": {
        +      "description": "When the run last wrote a note or finished a tool call. Absent for a terminal result and for a run that has done neither.",
        +      "type": [
        +        "null",
        +        "string"
        +      ]
        +    },
        +    "last_heartbeat_at": {
        +      "description": "Most recent durable executor heartbeat.",
        +      "type": [
        +        "null",
        +        "string"
        +      ]
        +    },
        +    "last_tool_step": {
        +      "description": "What this run last did with a tool: \"running <tool>\" while a call is in flight, otherwise \"completed <tool>\" for the most recent finished call. Absent for a terminal result and for a run with no tool-progress telemetry.",
        +      "type": "string"
        +    },
        +    "last_worklog": {
        +      "description": "The agent's most recent one-sentence note about what it is doing, from the run's durable event log. Absent for a terminal result and for a run that has written none.",
        +      "type": "string"
        +    },
        +    "pending_inputs": {
        +      "description": "Human inputs blocking an awaiting_input run.",
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "consent_tool": {
        +            "type": "string"
        +          },
        +          "kind": {
        +            "type": "string"
        +          },
        +          "prompt": {
        +            "type": "string"
        +          },
        +          "risk": {
        +            "type": "string"
        +          },
        +          "tool_call_id": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "tool_call_id",
        +          "kind",
        +          "prompt"
        +        ],
        +        "type": "object"
        +      },
        +      "type": [
        +        "null",
        +        "array"
        +      ]
        +    },
        +    "poll_after_ms": {
        +      "description": "Legacy spelling of poll_after_seconds in milliseconds; the two always agree. Prefer poll_after_seconds.",
        +      "type": "integer"
        +    },
        +    "poll_after_seconds": {
        +      "description": "Suggested seconds before polling again, paced to this run's recent tool-completion rate; absent for a terminal result.",
        +      "type": "integer"
        +    },
        +    "resume_run_id": {
        +      "description": "The exact auto-resume successor for an interrupted run; poll this run next.",
        +      "type": "string"
        +    },
        +    "resume_status": {
        +      "description": "Auto-resume disposition for an interrupted run: pending, resumed, failed, or unknown.",
        +      "type": "string"
        +    },
        +    "retryable": {
        +      "description": "Whether sending the same message again could plausibly succeed. False for a cause the same request would hit again, including time_limit — split the work or raise max_turn_seconds instead of retrying it unchanged.",
        +      "type": [
        +        "null",
        +        "boolean"
        +      ]
        +    },
        +    "run_id": {
        +      "description": "The public run identifier.",
        +      "type": "string"
        +    },
        +    "session_id": {
        +      "description": "The durable conversation/session identifier.",
        +      "type": "string"
        +    },
        +    "started_at": {
        +      "description": "When the run started.",
        +      "type": [
        +        "null",
        +        "string"
        +      ]
        +    },
        +    "status": {
        +      "description": "The current run status.",
        +      "type": "string"
        +    },
        +    "stop_reason": {
        +      "description": "Controller-selected stop reason, when present.",
        +      "type": "string"
        +    },
        +    "text": {
        +      "description": "The assistant's reply once the run has finished. While a run is still going this is the run's own status message, not an answer, and is often absent — read last_worklog and last_tool_step instead.",
        +      "type": "string"
        +    },
        +    "tokens": {
        +      "description": "Attributed token count; null when attribution is unavailable.",
        +      "type": [
        +        "null",
        +        "integer"
        +      ]
        +    },
        +    "tool_progress": {
        +      "additionalProperties": false,
        +      "description": "Durable tool execution progress; absent when this run has no tool-progress telemetry.",
        +      "properties": {
        +        "active_tools": {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "id": {
        +                "type": "string"
        +              },
        +              "name": {
        +                "type": "string"
        +              },
        +              "started_at": {
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "id",
        +              "name",
        +              "started_at"
        +            ],
        +            "type": "object"
        +          },
        +          "type": [
        +            "null",
        +            "array"
        +          ]
        +        },
        +        "completed_count": {
        +          "type": "integer"
        +        },
        +        "last_completed_at": {
        +          "type": [
        +            "null",
        +            "string"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "active_tools",
        +        "completed_count"
        +      ],
        +      "type": [
        +        "null",
        +        "object"
        +      ]
        +    },
        +    "upstream_status": {
        +      "description": "The model provider's HTTP status when this run died on an upstream fault; absent otherwise.",
        +      "type": "integer"
        +    },
        +    "url": {
        +      "description": "A deep link to this run's session in the plori web app.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "run_id",
        +    "session_id",
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedlist_agents1 field changed
      • changedOutput 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"
        +}
    • Changedlist_connections1 field changed
      • changedOutput 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"
        +}
    • Changedlist_pending_inputs1 field changed
      • changedOutput 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"
        +}
    • Changedlist_runs3 fields changed
      • addedInput schema / properties / cursor
        Added value: +{
        +  "description": "The next_cursor from a previous list_runs result, to continue where it stopped. Omit for the newest page.",
        +  "type": "string"
        +}
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "How many runs to return, newest first (default 20, maximum 100).",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • changedOutput 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"
        +}
    • Changedlist_workflow_executions1 field changed
      • changedOutput 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"
        +}
    • Changedlist_workflows1 field changed
      • changedOutput 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"
        +}
    • Changedrun_workflow1 field changed
      • changedOutput 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"
        +}
    • Changedschedule_run1 field changed
      • changedOutput 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"
        +}
    • Removedset_agent_model
    • Addedset_workflow_agent
  4. 2 tool updatesv0.9.1
    • Changedanswer_pending_input1 field changed
      • addedInput schema / properties / max_turn_seconds
        Added 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"
        +}
    • Changedinvoke_agent1 field changed
      • addedInput schema / properties / max_turn_seconds
        Added 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"
        +}
  5. 4 tool updatesv0.9.0
    • Addedcancel_run
    • Addededit_workflow
    • Addedget_workflow_version
    • Changedinvoke_agent1 field changed
      • addedInput schema / properties / max_turn_tokens
        Added 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"
        +}
  6. 14 tool updatesv0.7.0
    • Changedanswer_pending_input1 field changed
      • addedInput schema / properties / always_allow
        Added 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"
        +}
    • Changedcreate_agent1 field changed
      • changedInput schema / properties / model / description
        Previous 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."
    • Changedcreate_workflow1 field changed
      • changedInput schema / properties / agent_id / description
        Previous 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."
    • Addedget_agent
    • Addedget_usage
    • Addedget_workflow
    • Changedinvoke_agent1 field changed
      • changedInput schema / properties / session_id / description
        Previous 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."
    • Addedlist_connections
    • Addedlist_runs
    • Addedlist_workflow_executions
    • Changedlist_workflows1 field changed
      • addedInput schema / properties / agent_id
        Added value: +{
        +  "description": "Optional: a UUID of one of your agents to list only its workflows, or \"none\" for the unassigned ones.",
        +  "type": "string"
        +}
    • Addedrun_workflow
    • Addedschedule_run
    • Addedset_agent_model
  7. 13 tool updatesv0.3.0
    • Changedcreate_agent1 field changed
      • changedInput schema / properties / model / description
        Previous 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."
    • Removedget_agent
    • Changedget_credits1 field changed
      • addedInput schema / properties
        Added value: +{}
    • Changedget_disk1 field changed
      • addedInput schema / properties
        Added value: +{}
    • Removedget_usage
    • Changedinvoke_agent1 field changed
      • addedInput schema / properties / idempotency_key
        Added 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"
        +}
    • Changedlist_agents1 field changed
      • addedInput schema / properties
        Added value: +{}
    • Removedlist_brains
    • Removedlist_runs
    • Changedlist_workflows1 field changed
      • addedInput schema / properties
        Added value: +{}
    • Removedrun_workflow
    • Removedschedule_run
    • Removedset_agent_model
  8. 6 tool updatesv0.1.1
    • Changedcreate_agent1 field changed
      • changedInput schema / properties / name / description
        Previous value: -"A human-readable name for the agent."New value: +"The agent's name. Reusing a previous name returns that existing agent."
    • Addedcreate_workflow
    • Addedget_workflow_execution
    • Changedinvoke_agent1 field changed
      • changedInput schema / properties / wait / description
        Previous 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."
    • Addedlist_workflows
    • Addedrun_workflow
  9. 15 tool updatesv0.1.0
    • First observedanswer_pending_input
    • First observedcreate_agent
    • First observeddelete_agent
    • First observedget_agent
    • First observedget_credits
    • First observedget_disk
    • First observedget_run_result
    • First observedget_usage
    • First observedinvoke_agent
    • First observedlist_agents
    • First observedlist_brains
    • First observedlist_pending_inputs
    • First observedlist_runs
    • First observedschedule_run
    • First observedset_agent_model

TDQS

A4.1/5.0

Scored across 25 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count4/5

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.

Completeness4/5

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

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Host 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