fix(19.7): RA-WR-05 keep prompt Render errors out of the client's answer
promptHandler logs a failing Render's error with the prompt name and answers the fixed JSON-RPC internal error "pier: the prompt could not be rendered", as dispatch does for tool calls (A-WR-08), so database or provider text never reaches the agent or its transcript. TestPromptRenderError renders a prompt that fails with a database error naming its host and asserts, on both paths, that the client sees only the fixed text and the cause is in the log.
This commit is contained in:
@@ -121,7 +121,7 @@ What pier does with it at boot:
|
||||
- **Input.** `Input` is the zero value of a struct. A `path:"id"` field fills the `{id}` segment, a `query:"q"` field goes to the query string, every other field forms the JSON body; a `jsonschema:"..."` tag is the field's description and a field without `omitempty` is required. pier reflects the input schema from the struct, validates every call's arguments against it, and forwards the body as the agent sent it minus the path and query keys, so an update route that checks key presence sees exactly what the agent set. A `GET` or `DELETE` tool may carry only path and query fields, and an embedded struct on one fails boot (its promoted fields would be body fields). A `path:` field must be required: one with `omitempty` or `omitzero` fails boot. At call time pier passes a route only path values the HTTP mux could produce: a missing value, an empty, `.` or `..` segment, or a `/` inside a single-segment value is a tool error before the route runs. Numbers keep their literal digits in path and query values, so integer ids above 2^53 stay exact. `Output`, when set, is the struct the 2xx body matches and becomes the output schema.
|
||||
- **Annotations.** `GET` is read-only and idempotent, `PUT` idempotent, `DELETE` destructive; `ReadOnly`, `Destructive`, `Idempotent` and `OpenWorld` override. The read-only hint also decides what a read-only grant sees (below).
|
||||
- **Results.** A 2xx body is returned as text plus structured content (an object as is, any other JSON wrapped as `{"data": …}`); a 4xx or 5xx is a tool error carrying the route's own body, so the agent reads the real validation errors. A failure of the guard provider itself (for example a database error while resolving the principal) is the fixed tool error `pier: the tool could not be run for this caller`, logged server-side. The dispatched request carries the MCP request's `Host`, `X-Forwarded-Proto` and `X-Forwarded-Host`, so a route that builds absolute links builds them as over HTTP.
|
||||
- **Prompts.** A `pact.MCPPrompt` is prefixed and filtered like a tool, names its guard, declares its arguments, and renders its messages in `Render`; required arguments are checked first. A prompt never dispatches a route. Set `Writes` on a prompt whose text directs tools that are not read-only (for example "draft a post, then create it"): it then sits under the same read/write ceiling as those tools, so a read-only grant is not offered a prompt it cannot follow.
|
||||
- **Prompts.** A `pact.MCPPrompt` is prefixed and filtered like a tool, names its guard, declares its arguments, and renders its messages in `Render`; required arguments are checked first. A prompt never dispatches a route. An error `Render` returns is logged, and the agent gets only a fixed "the prompt could not be rendered" error. Set `Writes` on a prompt whose text directs tools that are not read-only (for example "draft a post, then create it"): it then sits under the same read/write ceiling as those tools, so a read-only grant is not offered a prompt it cannot follow.
|
||||
- **Descriptions.** `Title` and `Description` are static text, at most 1024 characters, passed through unchanged. Keep them factual one-liners and never build them from data: tool text is read by the model, so data-derived text would be a prompt-injection surface.
|
||||
|
||||
## Identity and sessions
|
||||
|
||||
Reference in New Issue
Block a user