Add request-side tool mediation controls#74
Conversation
Reviewer's GuideImplements the first slice of Wardwright request-side tool mediation for OpenAI-compatible Chat Completions: normalizing tool_mediation config, applying non-streaming patch rules to request tool catalogs, recording mediation metadata in receipts, expanding server-tool handling to dynamic Dune tools, and documenting the new control plane and OpenAPI schema surface. Sequence diagram for request-side tool mediation in complete_selected_modelsequenceDiagram
actor Agent
participant ServerTools as Wardwright.ServerTools
participant ToolMediation as Wardwright.ToolMediation
participant Core as Wardwright
Agent->>ServerTools: complete_selected_model(selected_model, request, config)
alt request.stream == true
ServerTools->>Core: complete_selected_model(selected_model, request, config)
Core-->>ServerTools: outcome
ServerTools-->>Agent: outcome
else tools == []
ServerTools->>ToolMediation: apply(request, config)
ToolMediation-->>ServerTools: {patched_request, mediation}
ServerTools->>Core: complete_selected_model(selected_model, patched_request, config)
Core-->>ServerTools: outcome
ServerTools->>ServerTools: add_tool_mediation_metadata(outcome, mediation)
ServerTools-->>Agent: outcome_with_mediation
else tools != []
ServerTools->>ServerTools: inject_tools(request, tools)
ServerTools->>ToolMediation: apply(request_with_tools, config)
ToolMediation-->>ServerTools: {patched_request, mediation}
ServerTools->>ServerTools: complete_with_tool_loop(selected_model, patched_request, config, tools)
ServerTools-->>ServerTools: outcome
ServerTools->>ServerTools: add_tool_mediation_metadata(outcome, mediation)
ServerTools-->>Agent: outcome_with_mediation
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 2 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="docs/tool-context-policy.md" line_range="134-138" />
<code_context>
output. Streaming, side-effecting tools, remote MCP passthrough, and hidden
provider tools remain deferred.
+Tool mediation is the broader control plane around this first server-tool
+surface. Request-side mediation can inspect agent-declared and Wardwright-added
+tool declarations, patch the provider-visible catalog, and receipt original vs
+final tool schema hashes under
+`final.provider_metadata.wardwright_tool_mediation`. See
</code_context>
<issue_to_address>
**issue (typo):** Consider adjusting phrasing around "and receipt original vs final" for grammatical clarity.
The phrase "and receipt original vs final tool schema hashes" reads as if it’s missing a preposition. Consider "and receipt of original vs final tool schema hashes" or "and record original vs final tool schema hashes" to make it grammatically complete.
```suggestion
Tool mediation is the broader control plane around this first server-tool
surface. Request-side mediation can inspect agent-declared and Wardwright-added
tool declarations, patch the provider-visible catalog, and record original vs
final tool schema hashes under
`final.provider_metadata.wardwright_tool_mediation`. See
```
</issue_to_address>
### Comment 2
<location path="docs/tool-mediation.md" line_range="133" />
<code_context>
+}
+```
+
+The hash records schema change without storing the full schema in every receipt.
+Future slices should add argument hashes, result hashes, tool-specific timing,
+approval evidence, and provider-hosted event normalization.
</code_context>
<issue_to_address>
**nitpick (typo):** The phrase "records schema change" is slightly awkward and could be smoothed out.
Very minor: consider rephrasing to "records the schema change" or "records schema changes" for more natural grammar.
```suggestion
The hash records the schema change without storing the full schema in every receipt.
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Pull request overview
Adds an initial “request-side tool mediation” control plane slice to Wardwright: operators can configure rule-based patching of provider-visible tool catalogs (hide/augment/replace) for non-streaming OpenAI-compatible chat completions, with receipt evidence capturing original vs provider-visible tool descriptors.
Changes:
- Documented the tool mediation model (visibility/execution taxonomy, extension modes, patch rule shapes, receipt evidence).
- Extended OpenAPI config schema and runtime config normalization to include
tool_mediation. - Implemented
Wardwright.ToolMediationand integrated it into the server-tool completion pipeline; expanded integration tests and the streaming-provider test harness for dynamic tool names.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/tool-mediation.md | New documentation for mediation model, patch rules, and receipt evidence. |
| docs/tool-context-policy.md | Links tool mediation into existing tool-context policy docs. |
| docs/index.md | Adds tool mediation to docs index navigation and status blurb. |
| contracts/openapi.yaml | Adds ToolMediation / ToolMediationRule schemas and wires into model config shapes. |
| app/lib/wardwright/tool_mediation.ex | Implements request-side tool catalog patching + receipt metadata emission. |
| app/lib/wardwright/server_tools.ex | Applies tool mediation before provider calls and stores mediation metadata in provider metadata. |
| app/lib/wardwright.ex | Adds tool_mediation defaults and normalization into config normalization pipeline. |
| app/test/stream_provider_transport_test.exs | Integration coverage for hide/augment/replace behavior + execute-mode dynamic Dune tool coverage. |
| app/test_support/router_case.ex | Updates test provider to support dynamic forwarded tool names and dynamic server-tool IDs. |
There was a problem hiding this comment.
Code Review
This pull request introduces a tool mediation control plane to Wardwright, enabling the inspection, patching, and replacement of tool declarations before they reach providers. It includes the new Wardwright.ToolMediation module, integration into the model completion flow, and updated API contracts and documentation. Review feedback highlighted several improvement opportunities: optimizing list appends to avoid O(N^2) performance, ensuring that mediation rules are only recorded in receipts when changes are actually applied, and addressing potential non-determinism in tool schema hashing due to map key ordering.
Summary
Adds the first Wardwright tool-mediation control-plane slice for issue #47.
tool_mediationpatchrules forhide,augment, andreplace0.1.0review pass coverage for canonical schema hashes, no-op mediation receipts, and replacement-name collision handlingCloses #47.
Validation
mise exec --command 'cd app && mix test'mise exec --command 'cd app && mix format --check-formatted'gitleaks protect --staged --config .gitleaks.toml --verbosemise run check:docsMIX_ENV=test mix muex --files "lib/wardwright/tool_mediation.ex" --test-paths "test/stream_provider_transport_test.exs" --max-mutations 40 --fail-at 80->40mutants,36killed,4invalid,0survived,100.0%mutation scoremise checkLimits
This PR does not claim native provider-hosted tool normalization or streaming tool-call mediation.
observe,mutate, andexecuteremain non-patching mediation modes until extension execution and provider-specific normalizers land.