Skip to content

feat(forge): emit an EBTE-style Tool-Call Claims section (template 4) - #282

Merged
ericksondelacruz merged 5 commits into
mainfrom
feat/forge-ebte-claims
Oct 28, 2026
Merged

ericksondelacruz merged 5 commits into
mainfrom
feat/forge-ebte-claims

Conversation

@ericksondelacruz

Copy link
Copy Markdown
Collaborator

Summary

trustabl forge now emits a ## Tool-Call Claims section in the generated SKILL.md, after the apply loop. It tells the coding agent to:

  • give every tool with an effect a typed claim argument (an EBTE ToolInvocationExplanation). A tool that only reads data the application already holds, for the current user, may skip it, and the tool registry marks which tools need one;
  • wire a mediation step outside the model that checks the claim against server-held facts before the call has any effect: deny on conflict, review on unknown, most restrictive wins. A missing or malformed claim, or an unknown schema_version, is a deny;
  • never treat the claim as granting authority.

Placement is emitted for each detected SDK (internal/forge/claimtext/sdk/). Every placement is one the Analyzer can see as a mediator, for example a tool input guardrail on OpenAI Agents or a shared decorator under @tool on LangChain, so a tool built from the skill doesn't trip the claims rules in #276 / #281.

TemplateVersion goes from 3 to 4, so trustabl forge check reports skills generated by template 3 as outdated.

Notes for review

Test plan

  • go build ./..., go vet ./..., go test ./... (27 packages ok), rebased on main at f0bebfa
  • Golden SKILL.md fixtures under testdata/forge/*/expected/ updated for the new section and template version
  • CI passes

trustabl forge now tells the coding agent to give every tool a typed
claim argument (ToolInvocationExplanation) and to wire a mediation step
that checks it against server-held facts before the call has any effect:
deny on conflict, review on unknown, most restrictive wins, and the claim
never grants authority. Placement is emitted per selected SDK.

TemplateVersion 3 -> 4, so forge check reports existing skills outdated.
The OpenAI Agents SDK runs a tool input guardrail before the tool with
the call's arguments, as its own examples/basic/tool_guardrails.py (in
the corpus) shows, so it is the mediation point to name. Wording only;
no template bump.
The LangChain block offered a graph node before the tool node as a
mediation point. The Analyzer cannot see a check there, so a tool
written that way gets LC-029 (claim nothing checks). The block now names
only a shared decorator stacked under @tool, which the Analyzer reads as
a wrapped claim.

The mediation step and the checklist said the step removes `claim`
before the tool body runs. The OpenAI tool input guardrail can only
allow or reject, so it cannot do that. They now say the step reads the
claim before any effect, removes it when it runs in a wrapper that can
change the arguments, and that nothing after the step acts on it.

Wording only, still unreleased template 4; no template bump.
Require the claim on every tool with an effect, not on every tool. A
tool that only reads data the application already holds, for the
current user, may skip it, and the tool registry marks which tools need
one. Tools the application does not define keep the existing controls
only. This matches the Analyzer, whose no-claim rule fires only on
side-effecting tools.

Keep a missing or malformed claim as a deny, and add an unknown
schema_version. This differs from the paper, which sends schema
failures to review: here a review would loop, since approving it
re-runs the same failing checks.

The other open questions are settled without code changes. The
field set stays minimal, the OpenAI guardrail placement is confirmed,
the Guard port waits for templates 2-4, and docs/forge.md stays out.

Wording only, still unreleased template 4; no template bump.
@ericksondelacruz
ericksondelacruz merged commit 35d821f into main Oct 28, 2026
5 checks passed
@ericksondelacruz
ericksondelacruz deleted the feat/forge-ebte-claims branch October 28, 2026 08:22
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.

2 participants