JuliusBrussee/caveman · error · TypeError

AutoGen requires a stable Caveman Scope for each agent or…

Error message

AutoGen requires a stable Caveman Scope for each agent or model context

What it means

The Caveman AutoGen middleware adapter requires an explicit Scope object to be passed alongside the runtime; the Scope anchors recovery sessions and config so each agent or model context has a stable identity. _check() raises this TypeError immediately at construction time when the scope argument is anything other than a caveman Scope instance (e.g. None, a string name, or a dict).

Solutions

  1. Create and pass a caveman Scope instance (from caveman_middleware import Scope; scope = Scope(...)) to the adapter constructor.
  2. If a scope name/config is stored elsewhere, reconstruct a Scope from it before constructing the client/workbench.
  3. Verify the imported Scope comes from caveman_middleware, not another package or an older major version.
  4. Check that no code path passes scope=None as a default; make scope a required constructor argument in your wrapper.

Example fix

// before
client = CavemanChatCompletionClient(inner_client, runtime=runtime, scope=None)
// after
from caveman_middleware import Scope
scope = Scope("agent-primary")
client = CavemanChatCompletionClient(inner_client, runtime=runtime, scope=scope)
Defensive patterns

Strategy: type-guard

Validate before calling

from caveman_middleware import Scope
if not isinstance(scope, Scope):
    raise TypeError(f"scope must be a caveman Scope, got {type(scope).__name__}")

Type guard

def is_scope(obj) -> bool:
    from caveman_middleware import Scope
    return isinstance(obj, Scope)

Try / catch

try:
    client = CavemanChatCompletionClient(inner, runtime=rt, scope=maybe_scope)
except TypeError as e:
    if "stable Caveman Scope" in str(e):
        client = CavemanChatCompletionClient(inner, runtime=rt, scope=Scope(default_name))
    else:
        raise

Prevention

When it happens

Trigger: Constructing CavemanChatCompletionClient or CavemanWorkbench (which both call _check via their __init__) with scope=None, with a string identifier, or with an object from a different library that is not caveman_middleware's Scope class.

Common situations: Passing a config dict instead of a Scope; forgetting to create a Scope after upgrading the middleware; building agents dynamically in loops and defaulting scope to None; mixing Scope classes from different caveman package versions.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/0e4cb7be11f62d84. Report an issue: GitHub.

Appendix: source

Thrown at packages/middleware/python/caveman_middleware/autogen.py:79

def _runtime(key):
    try:
        return _component_runtimes.get()[key]
    except KeyError:
        raise ValueError(f"Bind runtime {key!r} with caveman_middleware.autogen.component_runtimes before loading") from None


def _supported(runtime):
    return supports_framework(runtime, ("autogen-core", "0.7", "0.8"), ("autogen-agentchat", "0.7", "0.8"), ("autogen-ext", "0.7", "0.8"))


def _version_supported():
    return matches_framework(("autogen-core", "0.7", "0.8"), ("autogen-agentchat", "0.7", "0.8"), ("autogen-ext", "0.7", "0.8"))


def _check(runtime, scope):
    if not isinstance(scope, Scope):
        raise TypeError("AutoGen requires a stable Caveman Scope for each agent or model context")
    return runtime.as_async() if isinstance(runtime, MiddlewareRuntime) else runtime


def _schema():
    parameters = copy.deepcopy(RECOVERY_SCHEMA)
    # AutoGen's OpenAI structured-output helper rejects every non-strict tool,
    # even when that tool is not called. A stable strict schema remains usable
    # on typed calls; those calls still use only recovery-free transformations.
    parameters["required"] = list(parameters["properties"])
    return {"name": "caveman_retrieve", "description": RECOVERY_DESCRIPTION,
            "parameters": parameters, "strict": True}


def _observed_usage(result):
    if result is None or result.cached:
        return None
    # Native AutoGen converts an absent provider usage block to two zeros.
    # Preserve its CreateResult, but do not book those defaults as measurement.

View on GitHub (pinned to 3ee70a1026)