Propose Critic#
Source: examples/patterns/propose_critic.py
Introduction#
Self-Refine and related critique/revise work motivate iterative self-critique loops, and Human-AI collaboration by design explains why critique transparency is critical for trustworthy engineering decisions. This example demonstrates a propose-critic refinement cycle with bounded iterations and structured run output.
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
ProposeCriticPattern.run(...)with a fixedrequest_id.Read proposal, approval, and iteration fields directly from the typed
ProposeCriticResult.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["ProposeCriticPattern.run(...)"]
C --> D["proposal and critique turns iterate until stop criteria"]
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 pathlib import Path
5
6import design_research_agents as drag
7
8
9def main() -> None:
10 """Run propose/critique refinement orchestration with tracing."""
11 # Keep request ids deterministic so critique traces are easy to compare run-to-run.
12 request_id = "example-workflow-propose-critic-design-001"
13 tracer = drag.Tracer(
14 enabled=True,
15 trace_dir=Path("artifacts/examples/traces"),
16 enable_jsonl=True,
17 enable_console=True,
18 )
19 # The pattern needs only an LLM client when its delegates do not invoke tools.
20 with drag.LlamaCppServerLLMClient() as llm_client:
21 workflow = drag.ProposeCriticPattern(
22 llm_client=llm_client,
23 # Tracer is threaded through the pattern so proposer/critic turns share one timeline.
24 tracer=tracer,
25 )
26 result: drag.ProposeCriticResult = workflow.run(
27 prompt=(
28 "Write and iteratively improve a short engineering design rationale for using "
29 "modular connectors in field-serviceable devices."
30 ),
31 request_id=request_id,
32 )
33
34 # Print the results
35 summary = {
36 **result.summary(),
37 "proposal": result.proposal,
38 "approved": result.approved,
39 "iterations": result.iterations,
40 }
41 print(json.dumps(summary, ensure_ascii=True, indent=2, sort_keys=True))
42
43
44if __name__ == "__main__":
45 main()
Expected Results#
Run Command
PYTHONPATH=src python3 examples/patterns/propose_critic.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"
}
}