Files
deepseek-harness/.agents/notes/implemented/architecture/2026-06-11-runtime-arg-validation.md
Tianyi Cui 25dcd7293c docs: purge chain-of-thought leakage from prose
Delete design-session citations (decision/audit/plan ordinals, stack
positions), change narration, review choreography, and reviewer-addressed
justification from comments, JSDoc, docs, READMEs, Agent Notes, tests, and
generator templates; restate every affected fact as current-state contract
prose. Fix generated docs at their sources and regenerate the catalogs and
cordis-surface regions; re-paste type-equiv blocks; update every bilingual
counterpart and re-record the pairs. Record the citation rule in the
committed-artifact-citations Agent Note.
2026-08-09 21:10:59 +08:00

2.3 KiB

Agent Note: Runtime arg validation at the model boundary

Status: implemented

English | 中文

Problem

defineTool (the unified schema DSL) gives tool authors a typed execute(args) via the InferArgs<S> mapping. But that type is a compile-time claim about a value that arrives at runtime as model-generated JSON: nothing forced the model to honor the schema, so a malformed call — missing a required key, a string where a number was declared, or a literal outside the declared set — reached execute typed-in-name-only. The tool body then either crashed on the bad shape or silently misbehaved.

Decision

validateArgs(spec, args): string[] compiles a ParameterSchemaSpec and delegates to the shared validateJsonSchemaValue() walker, returning human-readable violations for a well-formed declaration. defineTool snapshots the compiled parameter schema at definition time and runs that validation before the typed body; violations throw ToolArgsError (INVALID_ARGS), which the registry returns as an error result the model can correct.

The validator and compiler therefore share exact semantics: the implicit parameter root is an open object; required keys come only from required: true; defaults remain annotations; explicit nested objects honor their declared openness; arrays recurse through items; scalar literal constraints are type-correct; and oneOf accepts exactly one matching branch. Raw-registered tools own their input validation.

Consequences

  • The model gets actionable feedback on its own malformed calls instead of an opaque crash, closing the gap between InferArgs's promise and runtime reality.
  • The validator and InferArgs must stay in agreement; a property test generates args satisfying a spec and asserts they pass validateArgs (with targeted corruptions rejected), closing that drift risk mechanically.
  • ToolArgsError subclasses HarnessError from the structured error taxonomy, keeping its code field; callers that read .message are unaffected by the hierarchy.
  • Validation cost is negligible next to a model call.