Multi Step JSON Tool Calling 1d Optimization#
Source: examples/optimization/multi_step_json_tool_calling_1d_optimization.py
Introduction#
Practical Bayesian optimization motivates iterative search over expensive objective evaluations, while Toolformer and Plan-and-Solve motivate explicit action/reason loops for model-guided exploration. This example operationalizes that idea as a JSON tool-calling optimization workflow with traceable proposals and evaluations.
Note
This example’s checked-in local LlamaCppServerLLMClient config uses a
Qwen3-4B GGUF model. On lower-RAM machines, swap in a smaller local
model or start with Ollama Local Client.
Technical Implementation#
Configure
Tracerwith JSONL + console output so each run emits machine-readable traces and lifecycle logs.Build the runtime surface (public APIs only) and execute
MultiStepAgent.run(...)with a fixedrequest_id.Configure and invoke
Toolboxintegrations (core/script/MCP/callable) before assembling the final payload.Print a compact JSON payload including
trace_infofor deterministic tests and docs examples.
flowchart LR
A["Input prompt or scenario"] --> B["main(): runtime wiring"]
B --> C["MultiStepAgent.run(...)"]
C --> D["optimization loop combines callable tools with explicit final answers"]
C --> E["Tracer JSONL + console events"]
D --> F["ExecutionResult/payload"]
E --> F
F --> G["Printed JSON output"]
1from __future__ import annotations
2
3import json
4from collections.abc import Mapping
5from pathlib import Path
6
7import design_research_agents as drag
8
9# This checked-in local config uses a Qwen3-4B GGUF model to exercise a richer
10# multi-step path. On lower-RAM machines, swap in a smaller local model or
11# start with the lighter Ollama local client example first.
12_EXAMPLE_LLAMA_CLIENT_KWARGS = {
13 "model": "Qwen_Qwen3-4B-Instruct-2507-Q4_K_M.gguf",
14 "hf_model_repo_id": "bartowski/Qwen_Qwen3-4B-Instruct-2507-GGUF",
15 "api_model": "qwen3-4b-instruct-2507-q4km",
16 "context_window": 8192,
17 "startup_timeout_seconds": 240.0,
18 "request_timeout_seconds": 240.0,
19}
20
21
22def _objective(x: float) -> float:
23 return x * x
24
25
26def main() -> None:
27 """Optimize ``x^2`` from ``x=3`` by letting the LLM choose each tool step."""
28 # Fixed request id keeps traces and docs output deterministic across runs.
29 request_id = "example-optimization-json-tool-calling-design-001"
30 tracer = drag.Tracer(
31 enabled=True,
32 trace_dir=Path("artifacts/examples/traces"),
33 enable_jsonl=True,
34 enable_console=True,
35 )
36 initial_x = 3.0
37 evaluation_history: list[dict[str, float]] = []
38
39 def _evaluate(payload: Mapping[str, object]) -> dict[str, object]:
40 raw_x = payload.get("x", initial_x)
41 x_value = float(raw_x) if isinstance(raw_x, (int, float)) else initial_x
42 f_x = _objective(x_value)
43 evaluation_record = {"x": x_value, "f_x": f_x}
44 evaluation_history.append(evaluation_record)
45 best_record = min(evaluation_history, key=lambda record: record["f_x"])
46 previous_record = evaluation_history[-2] if len(evaluation_history) > 1 else None
47 return {
48 "x": x_value,
49 "f_x": f_x,
50 "evaluations": len(evaluation_history),
51 "previous_x": None if previous_record is None else previous_record["x"],
52 "previous_f_x": None if previous_record is None else previous_record["f_x"],
53 "best_x": best_record["x"],
54 "best_objective": best_record["f_x"],
55 "improved_best": best_record is evaluation_record,
56 "history": list(evaluation_history),
57 }
58
59 # Run the optimization example using public runtime surfaces. Using this with statement will automatically
60 # shut down the managed client and tool runtime when the example is done.
61 with (
62 drag.Toolbox(
63 enable_core_tools=False,
64 callable_tools=(
65 drag.CallableToolConfig(
66 name="optimizer.evaluate",
67 description="Evaluate f(x) = x^2 at a proposed x and return the best observation so far.",
68 handler=_evaluate,
69 input_schema={
70 "type": "object",
71 "additionalProperties": False,
72 "properties": {"x": {"type": "number"}},
73 "required": ["x"],
74 },
75 ),
76 ),
77 ) as tools,
78 drag.LlamaCppServerLLMClient(**_EXAMPLE_LLAMA_CLIENT_KWARGS) as llm_client,
79 ):
80 optimization_agent = drag.MultiStepAgent(
81 mode="json",
82 llm_client=llm_client,
83 tool_runtime=tools,
84 max_steps=6,
85 # This example uses prompt guidance rather than tool-enforced step directions.
86 tool_calling_system_prompt=(
87 "You are solving a simple one-dimensional black-box minimization problem. "
88 "Use optimizer.evaluate to test concrete x values, and rely on observed tool results instead "
89 "of guessing numeric outcomes. Prefer a short, informative search that moves toward lower "
90 "observed objective values, then emit final_answer once the best observed x is well-supported."
91 ),
92 tracer=tracer,
93 )
94 result = optimization_agent.run(
95 prompt=(
96 "Minimize the black-box function f(x). Begin by evaluating x=3. "
97 "Use the observed results to choose a few better candidate x values, keeping the search efficient. "
98 "When you have enough evidence, emit final_answer with exactly the keys best_x, "
99 "best_objective, and evaluations, and use only values that came from tool observations."
100 ),
101 request_id=request_id,
102 )
103
104 # Print the results
105 summary = result.summary()
106 print(json.dumps(summary, ensure_ascii=True, indent=2, sort_keys=True))
107
108
109if __name__ == "__main__":
110 main()
Expected Results#
Run Command
PYTHONPATH=src python3 examples/optimization/multi_step_json_tool_calling_1d_optimization.py
Example output shape (values vary by run):
{
"success": true,
"final_output": "<example-specific payload>",
"terminated_reason": "<string-or-null>",
"error": null,
"trace": {
"request_id": "<request-id>",
"trace_dir": "artifacts/examples/traces",
"trace_path": "artifacts/examples/traces/run_<timestamp>_<request_id>.jsonl"
}
}