Expand description
DynamicSubmitTool — Provider-native structured output via tool injection
Implements rig’s ToolDyn trait with a runtime JSON schema as parameters.
When injected into an AgentBuilder, the LLM is forced to call
submit_result({...}) matching the schema, giving provider-side enforcement.
This is Layer 0 of Nika’s structured output defense system.
§How it works
The “Extractor pattern” from rig creates a synthetic tool whose parameters
field IS the target JSON schema. Combined with tool_choice: Required, the
LLM provider enforces schema compliance server-side (~90%+ first-attempt
success). The tool’s call() simply passes through the arguments — the
schema enforcement already happened at the provider level.
Unlike rig’s built-in Extractor (which requires compile-time Rust types via
#[derive(JsonSchema)]), DynamicSubmitTool accepts runtime serde_json::Value
schemas from YAML workflow definitions.
§Example
use nika::runtime::DynamicSubmitTool;
use rig::tool::ToolDyn;
let schema = serde_json::json!({
"type": "object",
"properties": { "name": { "type": "string" } },
"required": ["name"]
});
let tool = DynamicSubmitTool::new(schema);
let agent = AgentBuilder::new(model)
.tools(vec![Box::new(tool) as Box<dyn ToolDyn>])
.tool_choice(ToolChoice::Required)
.build();Structs§
- Dynamic
Submit Tool - A synthetic tool that forces the LLM to produce structured JSON output.