Improve the noop tool description to prevent recurring cross-tool field borrowing
Summary
Analysis of the last 24 h of agentic workflow runs (69 runs, 8 safe-output validator rejections) surfaced one new actionable tool-description gap: agents call noop with a correctly-serialized message string plus an extra details field. noop accepts only message/secrecy/integrity (additionalProperties: false), so the call is rejected.
This pattern has now recurred on 2 consecutive days across 2 different workflows, both Copilot, both reaching for details — meeting the escalation threshold recorded during the 2026-06-14 audit. The workflow prompts are correct (they ask for a run summary, not for a details field), so this is a tool-description gap, not a prompt issue.
🔍 Error analysis details
Error pattern: noop + details (cross-tool parity borrow)
Occurrences: 2 (2026-06-14, 2026-06-15) across 2 workflows.
What agents did wrong: passed a details field in addition to a valid message.
Example 1 — Slide Deck Maintainer (Run §27565130559, copilot, 2026-06-15):
{
"message": "Slide deck maintenance complete - no changes needed",
"details": {
"content_errors_found": 0,
"layout_issues_found": 0,
"slides_reviewed": 0,
"next_recommended_focus": "agentic-workflows",
"sources_checked": ["source-code"],
"notes": "slides/index.md is in Git LFS; LFS download blocked (403)..."
}
}
Rejected with: Invalid arguments: unknown parameter 'details'. Supported parameters for this tool: 'message', 'secrecy', 'integrity'. Recovered ~4 s later by folding everything into message.
Example 2 — PR Sous Chef (Run §27507600670, copilot, 2026-06-14): same tool, same details field, but carrying narrative prose instead of a structured object. Recovered ~3 s later.
Expected:
{ "message": "Slide deck maintenance complete - no changes needed. <metrics and notes folded into this single string>" }
Why this happened: details is a real field on the sibling safe-output tool report_incomplete (verified present in both runs' live tools/list). This is the same cross-tool parity-borrow failure mode already documented for submit_pull_request_review (agents borrowed item_number) and create_check_run (agents borrowed pull_request_number). The current noop description enumerates only two banned example fields (processed, skipped); the agent dutifully avoids those by serializing metrics into message, then reaches for the next plausible sibling field (details) for the extended/structured half of its summary. Enumerating specific examples shifts the agent to the next field rather than closing the gap.
Current tool description
From pkg/workflow/js/safe_outputs_tools.json (noop)
The message property currently reads: "... This is the only content field noop accepts. Serialize any metrics or structured run summary into this single string; additional named fields (for example processed, skipped) are not accepted and cause a missing-message error."
additionalProperties: false; required: message. Both the source copy (pkg/workflow/js/safe_outputs_tools.json) and the runtime copy (actions/setup/js/safe_outputs_tools.json) are in sync — no deployment gap.
Root cause analysis
- Enumerated-examples prohibition is insufficient. Naming
processed, skipped as the banned examples does not stop the agent from using a different plausible field (details). This is the identical failure mode that required generalizing the prohibitions on submit_pull_request_review and create_check_run.
details is borrowed from a sibling tool. report_incomplete genuinely accepts details, so the agent assumes parity.
- The error-message phrasing is inaccurate. The current text says additional fields "cause a missing-message error", but in both occurrences
message WAS present, so the real rejection was unknown parameter 'details'. The description over-promises one failure mode and misses the actual one.
Recommended improvements
Apply the same generalize-the-prohibition pattern used for submit_pull_request_review and create_check_run.
-
Lead with the prohibition at the tool-description level (not buried in the message property). Prepend to the noop description: "noop accepts ONLY a single message string (plus optional secrecy/integrity). It does NOT accept any other field — including details, reason, context, or any metric/summary name. Fold all metrics and structured run summaries into the message string."
-
Generalize and correct the message field description:
- Current: "... additional named fields (for example processed, skipped) are not accepted and cause a missing-message error."
- Suggested: "...
message is the ONLY content field. Any other named field (e.g. details, reason, context, processed, skipped, or any metric name) is rejected with an unknown parameter error — even when message is present. Serialize all metrics/structured summaries into this single string."
- Why: names the actually-observed offender (
details), generalizes beyond two examples, and fixes the inaccurate "missing-message error" claim.
-
Optionally add a one-line cross-reference distinguishing noop from report_incomplete (which DOES take details), since that is the source of the borrowed field.
Affected workflows
Slide Deck Maintainer — 1 (2026-06-15, structured-object details)
PR Sous Chef — 1 (2026-06-14, narrative-prose details)
Both recovered automatically within a few seconds, so no downstream output was lost — but the rejection wastes a turn and the pattern is spreading across workflows.
Implementation checklist
References
- Tool schema:
pkg/workflow/js/safe_outputs_tools.json + runtime copy actions/setup/js/safe_outputs_tools.json
- Sibling tool with a real
details field: report_incomplete
- Prior generalize-the-prohibition precedents:
submit_pull_request_review (item_number), create_check_run (pull_request_number)
Run IDs with errors: §27565130559, §27507600670
Generated by ⚡ Daily Safe Output Tool Optimizer · 450.6 AIC · ⌖ 32.5 AIC · ⊞ 9.7K · ◷
Improve the
nooptool description to prevent recurring cross-tool field borrowingSummary
Analysis of the last 24 h of agentic workflow runs (69 runs, 8 safe-output validator rejections) surfaced one new actionable tool-description gap: agents call
noopwith a correctly-serializedmessagestring plus an extradetailsfield.noopaccepts onlymessage/secrecy/integrity(additionalProperties: false), so the call is rejected.This pattern has now recurred on 2 consecutive days across 2 different workflows, both Copilot, both reaching for
details— meeting the escalation threshold recorded during the 2026-06-14 audit. The workflow prompts are correct (they ask for a run summary, not for adetailsfield), so this is a tool-description gap, not a prompt issue.🔍 Error analysis details
Error pattern:
noop+details(cross-tool parity borrow)Occurrences: 2 (2026-06-14, 2026-06-15) across 2 workflows.
What agents did wrong: passed a
detailsfield in addition to a validmessage.Example 1 — Slide Deck Maintainer (Run §27565130559, copilot, 2026-06-15):
{ "message": "Slide deck maintenance complete - no changes needed", "details": { "content_errors_found": 0, "layout_issues_found": 0, "slides_reviewed": 0, "next_recommended_focus": "agentic-workflows", "sources_checked": ["source-code"], "notes": "slides/index.md is in Git LFS; LFS download blocked (403)..." } }Rejected with:
Invalid arguments: unknown parameter 'details'. Supported parameters for this tool: 'message', 'secrecy', 'integrity'.Recovered ~4 s later by folding everything intomessage.Example 2 — PR Sous Chef (Run §27507600670, copilot, 2026-06-14): same tool, same
detailsfield, but carrying narrative prose instead of a structured object. Recovered ~3 s later.Expected:
{ "message": "Slide deck maintenance complete - no changes needed. <metrics and notes folded into this single string>" }Why this happened:
detailsis a real field on the sibling safe-output toolreport_incomplete(verified present in both runs' livetools/list). This is the same cross-tool parity-borrow failure mode already documented forsubmit_pull_request_review(agents borroweditem_number) andcreate_check_run(agents borrowedpull_request_number). The currentnoopdescription enumerates only two banned example fields (processed,skipped); the agent dutifully avoids those by serializing metrics intomessage, then reaches for the next plausible sibling field (details) for the extended/structured half of its summary. Enumerating specific examples shifts the agent to the next field rather than closing the gap.Current tool description
From
pkg/workflow/js/safe_outputs_tools.json(noop)The
messageproperty currently reads: "... This is the only content field noop accepts. Serialize any metrics or structured run summary into this single string; additional named fields (for example processed, skipped) are not accepted and cause a missing-message error."additionalProperties: false; required:message. Both the source copy (pkg/workflow/js/safe_outputs_tools.json) and the runtime copy (actions/setup/js/safe_outputs_tools.json) are in sync — no deployment gap.Root cause analysis
processed, skippedas the banned examples does not stop the agent from using a different plausible field (details). This is the identical failure mode that required generalizing the prohibitions onsubmit_pull_request_reviewandcreate_check_run.detailsis borrowed from a sibling tool.report_incompletegenuinely acceptsdetails, so the agent assumes parity.messageWAS present, so the real rejection wasunknown parameter 'details'. The description over-promises one failure mode and misses the actual one.Recommended improvements
Apply the same generalize-the-prohibition pattern used for
submit_pull_request_reviewandcreate_check_run.Lead with the prohibition at the tool-description level (not buried in the
messageproperty). Prepend to thenoopdescription: "noop accepts ONLY a singlemessagestring (plus optionalsecrecy/integrity). It does NOT accept any other field — includingdetails,reason,context, or any metric/summary name. Fold all metrics and structured run summaries into themessagestring."Generalize and correct the
messagefield description:messageis the ONLY content field. Any other named field (e.g.details,reason,context,processed,skipped, or any metric name) is rejected with anunknown parametererror — even whenmessageis present. Serialize all metrics/structured summaries into this single string."details), generalizes beyond two examples, and fixes the inaccurate "missing-message error" claim.Optionally add a one-line cross-reference distinguishing
noopfromreport_incomplete(which DOES takedetails), since that is the source of the borrowed field.Affected workflows
Slide Deck Maintainer— 1 (2026-06-15, structured-objectdetails)PR Sous Chef— 1 (2026-06-14, narrative-prosedetails)Both recovered automatically within a few seconds, so no downstream output was lost — but the rejection wastes a turn and the pattern is spreading across workflows.
Implementation checklist
noopdescription +messagefield description inpkg/workflow/js/safe_outputs_tools.jsonactions/setup/js/safe_outputs_tools.json(the 2026-05-30 deployment-gap lesson — keep both in sync)make buildandmake recompilemake test(ensureTestSafeOutputsToolsJSONInSyncstill passes)noop+ non-messagefield rejectionsReferences
pkg/workflow/js/safe_outputs_tools.json+ runtime copyactions/setup/js/safe_outputs_tools.jsondetailsfield:report_incompletesubmit_pull_request_review(item_number),create_check_run(pull_request_number)Run IDs with errors: §27565130559, §27507600670