docs(coding-agent): clarify that tool errors must be thrown, not returned
Returning { isError: true } from a tool's execute function was silently
ignored - the agent loop only sets isError via the catch block. Fix the
with-deps example to throw instead, add a clear note in the Tool Definition
docs section, and update the Error Handling summary.
closes #1881
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed `/new` leaving startup header content, including the changelog, visible after starting a fresh session ([#1880](https://github.com/badlogic/pi-mono/issues/1880))
|
- Fixed `/new` leaving startup header content, including the changelog, visible after starting a fresh session ([#1880](https://github.com/badlogic/pi-mono/issues/1880))
|
||||||
|
- Fixed misleading docs and example implying that returning `{ isError: true }` from a tool's `execute` function marks the execution as failed; errors must be signaled by throwing ([#1881](https://github.com/badlogic/pi-mono/issues/1881))
|
||||||
|
|
||||||
## [0.56.2] - 2026-03-05
|
## [0.56.2] - 2026-03-05
|
||||||
|
|
||||||
|
|||||||
@@ -1340,6 +1340,18 @@ pi.registerTool({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Signaling errors:** To mark a tool execution as failed (sets `isError: true` on the result and reports it to the LLM), throw an error from `execute`. Returning a value never sets the error flag regardless of what properties you include in the return object.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Correct: throw to signal an error
|
||||||
|
async execute(toolCallId, params) {
|
||||||
|
if (!isValid(params.input)) {
|
||||||
|
throw new Error(`Invalid input: ${params.input}`);
|
||||||
|
}
|
||||||
|
return { content: [{ type: "text", text: "OK" }], details: {} };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
**Important:** Use `StringEnum` from `@mariozechner/pi-ai` for string enums. `Type.Union`/`Type.Literal` doesn't work with Google's API.
|
**Important:** Use `StringEnum` from `@mariozechner/pi-ai` for string enums. `Type.Union`/`Type.Literal` doesn't work with Google's API.
|
||||||
|
|
||||||
### Overriding Built-in Tools
|
### Overriding Built-in Tools
|
||||||
@@ -1880,7 +1892,7 @@ const highlighted = highlightCode(code, lang, theme);
|
|||||||
|
|
||||||
- Extension errors are logged, agent continues
|
- Extension errors are logged, agent continues
|
||||||
- `tool_call` errors block the tool (fail-safe)
|
- `tool_call` errors block the tool (fail-safe)
|
||||||
- Tool `execute` errors are reported to the LLM with `isError: true`
|
- Tool `execute` errors must be signaled by throwing; the thrown error is caught, reported to the LLM with `isError: true`, and execution continues
|
||||||
|
|
||||||
## Mode Behavior
|
## Mode Behavior
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,7 @@ export default function (pi: ExtensionAPI) {
|
|||||||
execute: async (_toolCallId, params) => {
|
execute: async (_toolCallId, params) => {
|
||||||
const result = ms(params.duration as ms.StringValue);
|
const result = ms(params.duration as ms.StringValue);
|
||||||
if (result === undefined) {
|
if (result === undefined) {
|
||||||
return {
|
throw new Error(`Invalid duration: "${params.duration}"`);
|
||||||
content: [{ type: "text", text: `Invalid duration: "${params.duration}"` }],
|
|
||||||
isError: true,
|
|
||||||
details: {},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
content: [{ type: "text", text: `${params.duration} = ${result} milliseconds` }],
|
content: [{ type: "text", text: `${params.duration} = ${result} milliseconds` }],
|
||||||
|
|||||||
Reference in New Issue
Block a user