Skip to content

LOU-U12: send a structured error to the model when a tool throws - #37

Merged
LinuxDevil merged 1 commit into
mainfrom
lou-u12-tool-error-to-model
Oct 1, 2026
Merged

LinuxDevil merged 1 commit into
mainfrom
lou-u12-tool-error-to-model

Conversation

@LinuxDevil

Copy link
Copy Markdown
Owner

What

A thrown tool error now reaches the model as { error: <error name>, toolName, message } instead of the string null. Message only (no stack), capped at 2,000 chars with a ... (truncated) marker.

Why

The generic catch in doExecuteToolCall set result: null, so the model could not tell a tool failed or why, and could not recover. Mirrors the LOU-U4 validation-error shape.

How verified

  • npx tsc --noEmit: clean
  • npm run lint: 0 errors (442 pre-existing warnings, none added)
  • npm run build + create-loushy-agent build: success
  • npm run test:coverage: 89 files passed, exit 0
  • npm run fallow: 0 above threshold
  • npm run docs:verify-snippets: all 5 snippets type-check and run cleanly

New tests (src/execution/toolErrorResult.test.ts, scripted provider): structured error reaches the next request and the follow-up call succeeds; events/onToolResult/postToolCall still see error; truncation; non-Error throws; PropagatingToolError still aborts.

Notes for reviewer

  • outcome.error stays the plain message string (events/hooks unchanged); the structured object is only outcome.result. The original Error object is not newly exposed.
  • toolErrorMessage now falls back to String(error) for non-Error throws (previously undefined, which hid the error).
  • The LOU-T4 compaction is for provider.generate() failures and is untouched; both keep the {error, ...} family.
  • resume.ts (post-approval execution) still sends { error: message }; possible follow-up.

🤖 Generated with Claude Code

When a tool's execute threw an ordinary error, the generic path set result: null, so the model saw the string "null" and could not tell the tool failed or why. The result is now { error: <error name>, toolName, message } (message only, never a stack, capped at 2,000 chars with a truncation marker), mirroring the LOU-U4 argument-validation shape. PropagatingToolError still aborts the run; events, onToolResult and postToolCall still see outcome.error. toolErrorMessage now falls back to String(error) for non-Error throws so those still count as errors. Docs: api-overview 'Argument validation' became 'Tool errors'.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@LinuxDevil
LinuxDevil merged commit cc9008c into main Oct 1, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant