Skip to content
Build with Mellow

Tool execution contracts

Design structured inputs, results and permissions for callable capabilities.

In this topic

A useful tool gives the agent evidence it can use for the next decision. Mellow's tool envelope separates that evidence from a failure, a refusal, or a request that cannot run yet. Keep the result structured and the explanation specific; an HTTP success code alone does not mean the requested operation succeeded.

Success envelope

{
  "ok": true,
  "tool": "project_summary",
  "result": {
    "files_read": 4,
    "summary": "The project contains a website and its documentation."
  },
  "warnings": ["One unreadable file was omitted."]
}

result may be any JSON value. Prefer named fields for values the model should reuse, such as a file path or task identifier. Put nonfatal caveats in warnings; do not bury an actual failure inside a success sentence.

In native tools, ToolEnvelope.success(tool:result:warnings:) builds the JSON string. Its text convenience stores prose inside result.text:

return ToolEnvelope.success(tool: name, text: "Read four documents.")

Use structured directory entries with ready-to-use paths instead of requiring the agent to infer a path from a decorative tree. For paginated output, return the next cursor or page information alongside the entries.

Failure envelope

{
  "ok": false,
  "kind": "invalid_args",
  "message": "Choose a non-empty project identifier.",
  "field": "project_id",
  "expected": "a project identifier returned by the project list",
  "tool": "project_summary",
  "retryable": true
}
KindWhat happenedWhat the caller should do
invalid_argsMissing, malformed, or inappropriate argumentCorrect the named field before retrying
rejectedConfigured policy disallows the actionRespect the policy and choose an allowed operation
user_deniedThe user refused an approvalStop that action; do not repeat the same approval
permission_deniedRequired operating-system access is absentExplain the exact permission that must change
not_foundReferenced path is absentRe-list or select an existing path
tool_not_foundNo registered tool matchesRefresh capabilities or choose an available tool
unavailableCapability cannot run in its present stateResolve readiness, then retry if appropriate
timeoutExecution exceeded its time budgetInspect possible partial effects before retrying
execution_errorRuntime operation failedUse the returned cause to select recovery

retryable is guidance about a possible next attempt, not an instruction to repeat the request indefinitely. An invalid argument often becomes retryable only after correction. A timeout can leave a partially completed external action; check its state before risking a duplicate.

Validate before doing work

Parse JSON and validate required fields before opening files, starting processes, or contacting a service. Native MellowTool argument helpers can return a failure envelope with field and expected information. Do not replace a missing value with an unrelated default just to make execution proceed.

Schemas should describe actual executable inputs: expected path scope, units, accepted enum values, and whether a field is optional. A model seeing a schema still needs a useful error if a runtime condition changes after discovery.

Preserve the difference between authorization and execution

A tool can be registered but disabled for an agent. An enabled tool can require approval. An approved call can still lack a macOS privacy grant or fail in the underlying process. These are distinct states and should remain distinct in the result.

Always return the observed outcome. Do not report a saved file until writing succeeded. Do not report delivery until the channel confirmed the relevant operation. If a process was merely launched, return its identifier and explain how to inspect completion.

Detect and present outcomes

The core helpers include ToolEnvelope.isError, isSuccess, successPayload, and failureMessage. They preserve compatibility with older result forms inside the application. New tools should emit the current envelope rather than copying an older string-prefix convention.

The UI may render result.text as readable content; structured values remain useful to the agent and diagnostics. Keep tokens, passwords, and unrelated personal data out of both success payloads and exception messages.

Tools that control a run

Planning, completion, and clarification tools participate in the agent loop rather than performing an ordinary filesystem action. Their meaning must be preserved across the chat and API surfaces. Completion should settle the run; clarification should wait for the answer; cancellation should stop work and release its resources. Do not implement a tool named complete as a cosmetic message while background execution continues.

Test the entire exchange

Exercise valid input, missing input, denied policy, unavailable dependency, and a real execution failure. Then run a two-step conversation in which the second tool call uses a value from the first result. That verifies grounding and result shape together. Capture the arguments, envelope, visible card, and final continuation. Source reference: Packages/MellowCore/Tools/ToolEnvelope.swift.

Continue exploring · Build with MellowAuthor an extension →Start from a supported scaffold and validate an extension against the current runtime.