fix review findings: post-capture tool calls denied; schema snapshotted at start

Two bot findings on the structured runtime:

- Terminal means terminal WITHIN the step: a model response listing
  structured_output before further tool calls executed those calls after the
  final answer was accepted (the turn-continuation veto only fires at step
  end). A third runtime listener now denies every call for a captured agent
  at the tools/pre-execute gate — dispatch skipped, isError result naming the
  contract. Calls preceding the capture in the same response are untouched.

- The output schema is structuredClone'd before the subset assertion: the
  caller keeps its reference, so asserting and attaching the original let a
  post-start() mutation drift the enforced schema away from the asserted one.
  The clone pins assertion, model-visible parameters, and validation to one
  value.
This commit is contained in:
Tianyi Cui
2026-07-07 00:11:55 +08:00
parent 74502fa8c2
commit a520965f09
3 changed files with 122 additions and 6 deletions
@@ -119,9 +119,14 @@ export function startInProcessRun(
if (request.maxDepth !== undefined && childDepth > request.maxDepth) {
throw new SubagentDepthError(childDepth, request.maxDepth)
}
// Assert the schema subset BEFORE any child exists (the service has already
// capability-gated; this rejects a schema outside the enforced subset loud).
const schema = request.outputSchema
// Snapshot, then assert, the schema subset BEFORE any child exists (the
// service has already capability-gated; this rejects a schema outside the
// enforced subset loud). The snapshot is load-bearing: the caller keeps its
// reference, so validating and attaching the ORIGINAL would let a
// post-start() mutation drift the enforced schema away from the asserted
// one — the clone pins assertion, the model-visible parameters, and
// validateStructuredValue to the same isolation-immutable value.
const schema = request.outputSchema === undefined ? undefined : structuredClone(request.outputSchema)
if (schema !== undefined) assertSupportedOutputSchema(schema)
const childId = AgentId(randomUUID())