Skip to main content
Glama

Invoke agent

invoke_agent
Destructive

Send a message to an agent and get its reply or a run_id to poll for long-running work that outlives a single request.

Instructions

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.

Input Schema

TableJSON 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

TableJSON Schema
NameRequiredDescriptionDefault
urlNoA deep link to this run's session in the plori web app.
hintNoWhat to do next with this run, in one sentence. Present only while the run is non-terminal.
textNoThe assistant's reply once the run has finished. While a run is still going this is the run's own status message, not an answer, and is often absent — read last_worklog and last_tool_step instead.
causeNoMachine-readable cause for a non-normal terminal state.
errorNoWhy a terminal error or cancelled run failed, whether it was charged and what to do about it. Absent for a run that is still going or that finished normally.
filesNoFiles 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.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv0.17.0
    • addedOutput schema / properties / pending_inputs / items / properties / approve_url
      Added value: +{
      +  "type": "string"
      +}
  2. Changed4 schema fields changedv0.16.2
    • 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"
      +  ]
      +}
  3. Changed7 schema fields changedv0.16.0
    • 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"
      +}
  4. Changed1 schema field changedv0.9.1
    • 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. Changed1 schema field changedv0.9.0
    • 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. Changed1 schema field changedv0.7.0
    • 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."
  7. Changed1 schema field changedv0.3.0
    • 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"
      +}
  8. Changed1 schema field changedv0.1.1
    • 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."
  9. First observedv0.1.0

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.