Catalog PyPI
PACKAGE EXPLORERView in registry

advisor-middleware

PyPI

Anthropic's Advisor Strategy as a drop-in DeepAgents middleware — pair a powerful advisor with a fast executor

advisoragentclaudecost-optimizationdeepagentslangchainlanggraphllmmiddlewareopusstrategy
Versions collected1
Direct dependencies10From release 0.1.1
Last observed20 Oct, 20:04 UTC

README

Version 0.1.1 documentation


advisor-middleware

Anthropic's Advisor Strategy as a drop-in DeepAgents middleware.

PyPI License Python DeepAgents

Problem • How it works • Quick start • Configuration • Benchmark


Open-source implementation of Anthropic's Advisor Strategy — a pattern that pairs a fast, cheap executor model with a powerful advisor model. The executor runs end-to-end; the advisor is consulted only on critical decisions. Result: better performance at lower cost.

The Advisor Strategy

advisor-middleware makes this a single import for DeepAgents. It handles provider detection, native API routing, fallback invocation, cost guardrails, and context curation — so you just plug it in and your agents get smarter.


The Problem

Traditional sub-agent patternAdvisor Strategy
Large orchestrator decomposes work into tasksSmall executor drives end-to-end
Expensive model runs every turnExpensive model consulted only when needed
Worker pools + orchestration overheadZero orchestration — just a tool call
Hard to predict costsmax_uses guardrail caps advisor spend

How It Works

flowchart TD
    A["Executor (Sonnet/Haiku)"] -->|"Runs every turn"| B{"Stuck on a\nhard decision?"}
    B -->|No| C["Continue executing\n(read, write, search, execute)"]
    C --> A
    B -->|Yes| D["Call advisor tool"]
    D --> E["Advisor (Opus)\nReviews shared context"]
    E -->|"Returns plan/correction/stop"| F["Executor resumes\nwith guidance"]
    F --> A

    style A fill:#fff,stroke:#333,color:#333
    style E fill:#c0392b,color:#fff
    style C fill:#2d6a4f,color:#fff
    style F fill:#2d6a4f,color:#fff

The middleware operates in two modes depending on the executor's provider:

  • Native mode (Anthropic executor): Injects the advisor_20260301 server-side tool spec. The API handles everything internally — zero extra round-trips, zero overhead on simple turns.
  • Fallback mode (any provider): Exposes an advisor tool backed by a direct LLM call to the advisor model. Works with any executor/advisor combination.

Quick Start

Install

pip install advisor-middleware

# Or from source
pip install git+https://github.com/emanueleielo/advisor-middleware.git

Minimal — zero config

from deepagents import create_deep_agent
from advisor_middleware import AdvisorMiddleware

mw = AdvisorMiddleware(advisor_model="claude-opus-4-6")

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    system_prompt="You are a senior software engineer.",
    backend=backend,
    middleware=[mw],
)

That's it. Sonnet executes, Opus advises. The middleware auto-detects Anthropic and uses the native API tool — no extra configuration needed.

Cross-provider

from advisor_middleware import AdvisorMiddleware, AdvisorConfig

mw = AdvisorMiddleware(
    config=AdvisorConfig(
        advisor_model="anthropic:claude-opus-4-6",
        prefer_native=False,  # force fallback mode
        max_uses_per_turn=2,
    ),
)

agent = create_deep_agent(
    model="openai:gpt-4o",  # any provider as executor
    middleware=[mw],
)

With compact-middleware

from advisor_middleware import AdvisorMiddleware
from compact_middleware import CompactionMiddleware, CompactionToolMiddleware

advisor_mw = AdvisorMiddleware(advisor_model="claude-opus-4-6")
compact_mw = CompactionMiddleware(model="anthropic:claude-sonnet-4-6", backend=backend)
compact_tool_mw = CompactionToolMiddleware(compact_mw)

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    backend=backend,
    middleware=[advisor_mw, compact_mw, compact_tool_mw],
)

Configuration

AdvisorConfig

ParameterTypeDefaultDescription
advisor_modelstr | BaseChatModel"claude-opus-4-6"Advisor model ID or resolved instance
max_uses_per_turnint3Max advisor calls per agent turn
max_uses_per_sessionint | NoneNoneLifetime cap (None = unlimited)
prefer_nativeboolTrueUse native advisor_20260301 when possible
max_tokensint1024Max tokens the advisor can generate per consultation
temperaturefloat1.0Advisor temperature (fallback mode only)
advisor_system_promptstr | NoneNoneOverride advisor prompt (fallback only)
contextContextCurationConfig(see below)Controls context forwarded to advisor

ContextCurationConfig

ParameterTypeDefaultDescription
include_system_promptboolTrueForward executor's system prompt
include_tool_resultsboolTrueInclude tool results in context
max_context_messagesint | NoneNoneLimit messages sent to advisor
max_context_charsint | NoneNoneHard character budget for context

Cost control example

config = AdvisorConfig(
    max_uses_per_turn=2,        # max 2 consultations per turn
    max_uses_per_session=10,    # max 10 total in the session
    context=ContextCurationConfig(
        max_context_messages=10,  # only last 10 messages
        include_tool_results=False,  # skip bulky tool outputs
    ),
)

Native vs Fallback

Native (advisor_20260301)Fallback (LLM call)
WhenAnthropic executor + prefer_native=TrueAny other executor, or prefer_native=False
HowServer-side tool spec injected into API callDirect LLM call to advisor model
Round-trips0 extra (handled by API)1 per consultation
OverheadZero on simple turnsMinimal (only when called)
Model freedomAnthropic advisor onlyAny model as advisor
Context curationHandled by APIConfigurable via ContextCurationConfig

The middleware auto-detects the executor's provider and routes accordingly. You can force fallback mode with prefer_native=False for full control over context curation.


Benchmark

We tested with a real debugging task: a 4-file async task queue system (connection pool + circuit breaker + rate limiter + retry logic) with interacting bugs that cause tasks to be silently dropped under load. The agent must read all files, diagnose cross-component interactions, and fix every bug.

python examples/benchmark.py

Results: Haiku solo vs Haiku + Opus Advisor

Haiku SoloHaiku + Opus Advisor
Tests passing11/1212/12
Turns116
File writes7 (3 rewrites)3 (all correct first try)
Advisor calls01
Duration210.7s90.3s

What happened: Haiku solo rewrote connection.py four times, going in circles trying to fix the semaphore leak. It never solved the circuit breaker recovery issue.

Haiku + Advisor consulted Opus once after reading all files. Opus confirmed the bug diagnosis, corrected a proposed fix, and flagged an issue Haiku missed. Haiku then wrote all three fixes correctly on the first attempt.

Why it works

The advisor doesn't help on simple tasks — Haiku handles routine reads, writes, and obvious fixes alone. The value shows on cross-file reasoning where Haiku gets stuck in trial-and-error loops:

  • Opus identified that a semaphore release was needed for each discarded connection, not just one
  • Opus correctly noted the circuit breaker race condition is a non-issue under asyncio's GIL (avoiding an unnecessary lock)
  • Opus flagged that rate-limit timeouts should requeue tasks without consuming retry attempts

One well-timed consultation eliminated multiple cycles of incorrect rewrites.

Anthropic's benchmarks

From the original blog post:

ConfigSWE-bench MultilingualCost per task
Sonnet + Opus Advisor+2.7pp vs Sonnet solo-11.9%
Haiku + Opus Advisor (BrowseComp)41.2% vs 19.7% solo85% cheaper than Sonnet

Introspection

Track advisor usage programmatically:

mw = AdvisorMiddleware(advisor_model="claude-opus-4-6")

# ... after agent execution ...

print(f"Total consultations: {mw.get_total_uses()}")
print(f"Total advisor tokens: {mw.get_total_advisor_tokens()}")

for event in mw.get_events():
    print(f"  Turn {event['turn']}: {event['strategy']} — {event['advisor_tokens']} tokens")
    print(f"    Q: {event['question'][:80]}...")
    print(f"    A: {event['advice'][:80]}...")

Architecture

advisor_middleware/
├── __init__.py        # Public API: AdvisorMiddleware, AdvisorConfig, ...
├── middleware.py       # Core middleware — dual-mode wrap_model_call
├── config.py          # AdvisorConfig + ContextCurationConfig dataclasses
├── state.py           # AdvisorState + AdvisorEvent TypedDicts
├── prompts.py         # Executor + advisor system prompts
├── providers.py       # Provider detection, native spec, fallback invocation
└── py.typed           # PEP 561 type marker

Development

# Install with dev dependencies
pip install -e ".[dev,deepagents,anthropic]"

# Run tests
pytest

# Lint
ruff check advisor_middleware/

# Type check
mypy advisor_middleware/

License

MIT — Emanuele Ielo

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.110 Apr 202610

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
emanueleielo/advisor-middleware

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 20:04 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:aebbab3fce87e29d3e308ab8458ae4cb2802fad0d075acc50a58adaf33602614