Install any skill in seconds. Free to start, no credit card required.
Get Started Free →ENHANCE overlay on [[dspy]] — the upfront rubric for choosing a reasoning SHAPE (Predict / ChainOfThought / ReAct / ProgramOfThought) BEFORE you write a prompt or pick an optimizer. The local `dspy` skill lists the modules but never surfaces the *selection criterion*: reasoning shape is chosen by task structure, not by reflexively defaulting to CoT. Activate every time a new LM-calling node/step is added to a pipeline. Do NOT activate for one-shot prompts, optimizer/teleprompter choice (that is
.claude/skills/agentsope-agentsop-module-shape-selection/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 194% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 180% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 137% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 147% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 185% | 0% |
> "Pick the lowest-power Module that works. Default to ChainOfThought." > — DSPy docs dspy.ai/learn/programming/modules/] > > This overlay sharpens that line into a rubric: the default is not a law. The > shape is a function of the task structure, and CoT is only one of four answers.
This is an enhancement overlay. It assumes the dspy]] library skill is loaded (it provides dspy.Predict, dspy.ChainOfThought, dspy.ReAct, dspy.ProgramOfThought APIs and install). This file adds only the decision the lib skill leaves implicit. Cross-link: dspy]], and the optimizer SOP [[agentsop-dspy]].
Activate the instant you are about to add or wrap an LM-calling step:
| Trigger | Signal | |---|---| | New node | A LangGraph/CrewAI node body, or a forward() line, is about to call an LM | | New dspy.<Module>(Sig) | You are typing dspy.ChainOfThought(...) on reflex — stop and run the rubric | | Refactor | An existing Predict "feels weak" or a ChainOfThought "feels wasteful" | | Pipeline growth | A multi-stage program adds a stage; each stage needs its own shape decision | | Tool appears | A function/API/search/calculator is now available to the step |
Do NOT activate when:
that is the agentsop-dspy]] workflow, a later stage. Shape comes first, optimizer second.
if, a DB read, a deterministic transform).Shape selection is upstream of optimization. You pick the shape in Stage 1 (Programming) of the dspy SOP, before any metric or compile dspy.ai/learn/].
> Reasoning shape is chosen by task structure, not by defaulting to CoT.
The lib skill shows four modules side by side and a "Best Practices" note that says "Start with Predict, add ChainOfThought if needed" ~/.claude/skills/dspy Best Practices §1]. In practice that collapses into a CoT-everywhere reflex, because "if needed" is never operationalized. This overlay operationalizes it.
A module's shape is the control-flow contract between the LM and your code:
does the answer need is there a real
intermediate reasoning? tool to call?
│ │
simple lookup ── no ──┤ │
/classify ─────────►│ Predict │
│ │
analytic / ── yes ──┤── no tool ──────────────►│ ChainOfThought
judgement │ │
│ │
needs to act ─────────┼── yes, real tool ───────►│ ReAct(tools=[...])
/look things up │ │
│ │
math / counting ──────┴── deterministic compute ► ProgramOfThought
/ strict parsing (code grounds answer)Three shifts the agent must internalize:
unsure, CoT is the safe baseline" — not "always ship CoT." Every CoT you ship that a Predict would have matched is pure token tax dspy.ai/learn/programming/modules/].
(this overlay). Optimizer = which demos/instructions get baked in (agentsop-dspy]] §4). A wrong shape cannot be fixed by a better optimizer — MIPROv2 on the wrong shape just optimizes the wrong thing dspy.ai/learn/optimization/overview/].
call + a reasoning/rationale field (more output tokens). ReAct ≈ N calls (a tool loop). PoT ≈ 1 LM call + code execution. Shape choice is a cost choice.
A three-step gate, run per LM-calling step (not per pipeline):
Answer two yes/no questions about the step's output:
(Multi-hop inference, judgement, "why", trade-off weighing → yes. Lookup, label, format-conversion → no.)
or running deterministic computation? (Search/API/DB → tool. Arithmetic/counting/strict-parse → computation. Neither → no.)
Map the (Q1, Q2) answers straight onto the card. Do not negotiate with the reflex.
A shape is only justified if it beats the cheaper shape below it. Before shipping anything heavier than Predict:
dspy.inspect_history(n=3) dspy.ai/learn/programming/modules/].Predict produce the same labels on a classify task, ship Predict.
intermediate/operation_candidates.json so the next node reusesthe reasoning instead of re-deriving it.
Exit criterion: the chosen shape produces plausible outputs on 5+ examples AND no cheaper shape matches it. Then — and only then — proceed to metric + optimizer (agentsop-dspy]]).
| Task structure | Shape | DSPy module | Cost signature | Evidence | |---|---|---|---|---| | Lookup / classify / extract / format-convert (no reasoning needed) | Predict | dspy.Predict(Sig) | 1 call, no reasoning tokens — lowest overhead | dspy.ai/learn/programming/modules/], lib Predict §2 | | Analytic / judgement / multi-hop inference (reasoning helps, no tool) | Chain of Thought | dspy.ChainOfThought(Sig) | 1 call + reasoning/rationale field — adds output tokens | dspy.ai/learn/programming/modules/], lib ChainOfThought §2 | | Tool-use: search / API / DB / retrieval / calculator | ReAct | dspy.ReAct(Sig, tools=[...]) | N calls — a think→act→observe loop | dspy.ai/learn/programming/modules/], lib ReAct §2 | | Math / counting / unit conversion / strict parsing | Program of Thought | dspy.ProgramOfThought(Sig) | 1 LM call → generated code → executed; answer grounded in execution | dspy.ai/learn/programming/modules/], lib ProgramOfThought §2 |
ChainOfThought adds a generated reasoning field to every call. On a high-volume classify step (e.g. routing 100k tickets/day), that reasoning field is pure cost with zero accuracy gain if the labels don't change. The lib skill's "add CoT if needed" lib Best Practices §1] is correct but under-specified: needed means "Step 3 measured a lift." Default to CoT when unsure; ship Predict when measured equal.
| Situation | Action | Why | |---|---|---| | Math task but you trust the LM's mental arithmetic | Still prefer PoT | Code execution removes arithmetic hallucination dspy.ai/learn/programming/modules/] | | Reasoning helps AND a tool exists | ReAct (it does CoT inside the loop) | ReAct subsumes CoT when tools are present | | Hard analytic case, single CoT is unstable | dspy.MultiChainComparison / dspy.majority over N CoT samples | Vote across samples — escalation, not a base shape dspy-sop §4.2] | | "Tool" is actually a pure Python function with no I/O | Inline the function; use CoT or Predict, not ReAct | A ReAct loop with a trivial deterministic helper is wasted calls (Case B) |
no reasoning, no tool → Predict
reasoning, no tool → ChainOfThought
any real tool / action → ReAct(tools=[...])
math / count / strict parse → ProgramOfThought困境: A pipeline routes incoming support tickets into 6 categories. The engineer's reflex was dspy.ChainOfThought("ticket -> category") because "reasoning is always safer." Volume is 100k tickets/day. Is the reasoning field earning its cost?
约束:
reasoning field (extra output tokens) × 100k/day.决策步骤 (Step 3 of the SOP, made concrete):
"needs a tool/compute?" → no. The card says Predict.
dspy.inspect_history(n=3) dspy.ai/learn/programming/modules/].
pure token tax at 100k/day. Ship Predict.
move ambiguity handling to a second, cheap Predict triage stage.
结果: On closed-set classification, Predict typically matches CoT. The CoT-everywhere reflex would have shipped a per-call reasoning surcharge for no accuracy.
可提取的操作: A closed-set classify/lookup step defaults to Predict. Promote to CoT only after Step 3 measures a label change — never on reflex.
困境: An engineer wants an "agentic" answer step and writes dspy.ReAct("question -> answer", tools=[]) — or with a single trivial helper that does no real I/O. Is this actually agentic?
约束:
DB) dspy.ai/learn/programming/modules/, lib ReAct §2].
i.e. CoT — but pays for loop overhead and added parsing/failure surface.
决策步骤:
The card routes away from ReAct.
the action/observation steps are dead weight that can hang or mis-parse.
dspy.ChainOfThought directly. If it doesn't →dspy.Predict.
dspy.ReAct(tools=[...]) back only when a real external capability appears(web search, retrieval, calculator API). Then ReAct subsumes CoT inside its loop.
结果: Replacing tool-less ReAct with CoT removes loop overhead and a class of tool-parsing failures while preserving the reasoning. No capability is lost because none existed.
可提取的操作: ReAct earns its loop only when at least one real, I/O-bearing tool exists. Tool-less ReAct → downgrade to CoT (or Predict).
困境: A step computes "15% of 240, then subtract the 3-item average." The reflex is ChainOfThought because it "shows the math." Is shown arithmetic correct arithmetic?
约束:
ProgramOfThought generates and executes code, grounding the number in a realcomputation dspy.ai/learn/programming/modules/, lib ProgramOfThought §2].
决策步骤:
ProgramOfThought, not CoT.
dspy.ProgramOfThought("question -> answer"); it emits answer = 240*0.15 - ...and runs it lib ProgramOfThought §2].
ambiguous — then compose: CoT to extract operands → PoT to compute.
结果: PoT removes arithmetic hallucination at the cost of one code execution. CoT on the same step ships numbers that look derived but may be wrong.
可提取的操作: Any step whose answer is a computed number/count/parse defaults to PoT. CoT's prose is not a substitute for executed code.
dspy.ChainOfThought on every step"to be safe." Safe ≠ free; the reasoning field is a per-call token tax. CoT is the default when unsure, not the default always (Case A) dspy.ai/learn/programming/modules/].
ReAct(tools=[]) or a ReAct over a trivial purefunction is just CoT plus loop overhead and extra failure modes (Case B).
executing it. Use PoT for computed answers (Case C).
decision; choosing it post-hoc means the prompt was written against the wrong contract.
repair a wrong shape; it optimizes whatever shape you gave it dspy.ai/learn/optimization/overview/].
needs multi-hop reasoning — the mirror failure of the CoT reflex.
a retrieve→reason→format pipeline may be ReAct→CoT→Predict.
here — see agentsop-dspy]] §4. Shape first, optimizer second.
desc=): the lib skill dspy]] CoreConcepts §1. Shape assumes the signature exists.
to shape (agentsop-dspy]] §7).
The shape decision is framework-independent; only the spelling changes.
| Reasoning shape | DSPy module | LangChain equivalent | Raw-prompting equivalent | |---|---|---|---| | Predict (lookup/classify, no reasoning) | dspy.Predict(Sig) | LLMChain / direct model.invoke with a plain template | Single prompt, "answer directly" — no scratchpad | | Chain of Thought (analytic, no tool) | dspy.ChainOfThought(Sig) | LLMChain with a "think step by step" prompt; no agent | "Let's think step by step…" then answer | | ReAct (tool-use loop) | dspy.ReAct(Sig, tools=[...]) | create_react_agent / AgentType.ZERO_SHOT_REACT_DESCRIPTION + tools | Manual Thought/Action/Observation loop you parse yourself | | Program of Thought (math/parse via code) | dspy.ProgramOfThought(Sig) | PythonREPLTool agent / LLMMathChain | "Write Python to compute the answer," then exec |
Reading the table: the task-structure question (reasoning? tool? compute?) is the invariant. DSPy makes the choice a one-line module swap with a stable signature; LangChain makes it an agent-type/chain choice; raw prompting makes it a scratchpad-format choice you hand-maintain. The selection rubric in §3–§4 is the same in all three columns — only the binding to code differs. This is why the overlay lives above dspy]]: the rubric transfers even when you leave DSPy.
Bridge to the rest of the stack: once the shape is chosen here, hand off to agentsop-dspy]] for metric + optimizer + compile, and to dspy]] for the module API, signature syntax, and LM-provider wiring.
dspy-sop SKILL.md §3 (Stage 1 module pick), §4.2 (module selection table)~/.claude/skills/dspy/SKILL.md §Core Concepts 2 (Predict/CoT/ReAct/PoTexamples), Best Practices §1 ("start simple, iterate")
references/R1-source-evidence.mdintermediate/operation_candidates.json| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-04 | pass→pass | 7,446 | 6,100 | -18% | 1 | 1 | 0% | 1,210 | 5,473 | +352% | 0 | 0 | — |
case-01 | pass→pass | 17,914 | 15,109 | -16% | 1 | 1 | 0% | 3,035 | 6,861 | +126% | 0 | 0 | — |
case-02 | pass→pass | 12,800 | 7,882 | -38% | 1 | 1 | 0% | 2,103 | 5,744 | +173% | 0 | 0 | — |
case-03 | pass→pass | 10,161 | 8,364 | -18% | 1 | 1 | 0% | 1,536 | 5,862 | +282% | 0 | 0 | — |
case-05 | fail→pass | 13,847 | 11,875 | -14% | 1 | 1 | 0% | 2,261 | 6,639 | +194% | 0 | 0 | — |
case-06 | pass→pass | 11,174 | 9,409 | -16% | 1 | 1 | 0% | 1,640 | 5,991 | +265% | 0 | 0 | — |
case-07 | pass→pass | 12,646 | 11,709 | -7% | 1 | 1 | 0% | 2,083 | 6,535 | +214% | 0 | 0 | — |
case-08 | pass→pass | 10,373 | 8,650 | -17% | 1 | 1 | 0% | 1,871 | 6,122 | +227% | 0 | 0 | — |
case-09 | pass→pass | 5,335 | 4,176 | -22% | 1 | 1 | 0% | 965 | 5,182 | +437% | 0 | 0 | — |
case-10 | fail→pass | 14,088 | 8,765 | -38% | 1 | 1 | 0% | 2,129 | 5,957 | +180% | 0 | 0 | — |
case-11 | pass→pass | 13,528 | 10,498 | -22% | 1 | 1 | 0% | 2,309 | 6,342 | +175% | 0 | 0 | — |
case-12 | pass→pass | 21,073 | 17,064 | -19% | 1 | 1 | 0% | 3,553 | 7,452 | +110% | 0 | 0 | — |
case-13 | fail→pass | 16,954 | 12,709 | -25% | 1 | 1 | 0% | 2,808 | 6,644 | +137% | 0 | 0 | — |
case-14 | pass→pass | 16,193 | 7,779 | -52% | 1 | 1 | 0% | 2,716 | 5,716 | +110% | 0 | 0 | — |
case-15 | fail→pass | 15,656 | 12,022 | -23% | 1 | 1 | 0% | 2,639 | 6,512 | +147% | 0 | 0 | — |
case-16 | fail→pass | 13,046 | 11,839 | -9% | 1 | 1 | 0% | 2,262 | 6,442 | +185% | 0 | 0 | — |
case-17 | pass→pass | 12,323 | 10,735 | -13% | 1 | 1 | 0% | 1,913 | 6,234 | +226% | 0 | 0 | — |
case-18 | fail→pass | 10,967 | 6,249 | -43% | 1 | 1 | 0% | 1,728 | 5,539 | +221% | 0 | 0 | — |
case-19 | pass→pass | 8,843 | 6,633 | -25% | 1 | 1 | 0% | 1,360 | 5,533 | +307% | 0 | 0 | — |
case-20 | fail→pass | 16,868 | 8,389 | -50% | 1 | 1 | 0% | 2,859 | 5,990 | +110% | 0 | 0 | — |
case-21 | pass→pass | 10,517 | 8,108 | -23% | 1 | 1 | 0% | 1,790 | 5,901 | +230% | 0 | 0 | — |
case-22 | pass→pass | 3,805 | 3,958 | +4% | 1 | 1 | 0% | 608 | 5,207 | +756% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +32 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.