Skip to content

Self-Discovery: Choose The Strategy Before Solving

Some failures are not about inability. They are about using the wrong strategy. For a rainy easy-walking food trip, the assistant may first need modules like decompose constraints, verify route, and check walking effort.

Self-Discovery asks the model to choose strategy modules first, then solve using those modules.

One Sentence

Self-Discovery turns direct solving into select strategy modules, then solve, so the model commits to a method before details.

What Breaks Without It

Problem What it looks like Risk
Direct answer Fast Wrong strategy
Strategies live in prompt Comprehensive Model may ignore them
Module library is huge Flexible Selection becomes random

What This Pattern Changes

Who Owns
Module library Provides reusable strategies
Model Selects modules for this task
Solver Answers using selected modules
Python Validates module names and traces selection

Modules should be checklists, not slogans.

Walk Through One Trace

Stage Output
Available modules decompose, verify, analogy
Selection decompose, verify
Solve Answer using decompose+verify

For travel, modules might be: decompose constraints, check weather fit, check walking load.

Flow

flowchart TD
  T["Task"] --> L["Read module library"]
  L --> S["Select modules"]
  S --> V["Validate module names"]
  V --> A["Solve using modules"]
  A --> O["Answer"]

Code Walk

result = self_discovery(
    model,
    task="Solve something.",
    available_modules=["decompose", "verify", "analogy"],
    tracer=tracer,
)

Full example:

from __future__ import annotations

from pathlib import Path

from agent_patterns_lab.patterns.self_discovery import self_discovery
from agent_patterns_lab.runtime import MockLLM, Tracer


def main() -> None:
    tracer = Tracer()
    model = MockLLM(['{"modules":["decompose","verify"]}', "Answer using decompose+verify"])

    result = self_discovery(
        model,
        task="Solve something.",
        available_modules=["decompose", "verify", "analogy"],
        tracer=tracer,
    )

    print(result.answer)
    trace_path = tracer.export_jsonl(Path(".traces") / "55_self_discovery.jsonl")
    print(f"[trace] {trace_path}")


if __name__ == "__main__":
    main()

Run:

UV_CACHE_DIR=.uv_cache PYTHONPATH=src uv run --no-sync python examples/55_self_discovery.py

Nearby Patterns

Pattern Who decides next Use when
Plan & Solve Model writes steps Task needs decomposition
Self-Discovery Model selects strategy modules Task needs the right method
LATS Search compares candidates Multiple solutions need scoring
Routing Route selects external flow Inputs need different pipelines

When To Use It

  • You have a small clear module library.
  • The model often fails from wrong strategy.
  • Strategy selection is cheaper than search.
  • You want consistency across similar tasks.

When Not To Use It

  • Module descriptions are vague.
  • There are too many modules.
  • The task is simple.
  • Selected modules have no required checkpoints.

Costs And Common Failures

Failure Symptom Fix
Slogan modules "Be logical" Define input/output/checklist
Selects but ignores Strategy theater Bind checkpoints to each module
Too many modules Selection drift Limit library and max selected
Wrong module Bad direction Allow reselect after quick check

Self-Discovery fits choosing a method first.

For task steps, read Plan & Solve. For candidate search, read LATS.

References