Skip to Content
DocsMigrationsLoom 0.1 → 0.2

Migrating from 0.1 → 0.2

Loomflow 0.2.0 is mostly additive but ships two breaking changes. This guide shows what to change and why.

TL;DR

- agent = Agent("You are helpful.") + agent = Agent("You are helpful.", model="claude-opus-4-7")
- with pytest.raises(ValueError): - Agent("hi", model="bad-spec") + from loomflow.core.errors import ConfigError + with pytest.raises(ConfigError): + Agent("hi", model="bad-spec")

That’s it for breaking changes. Everything else in 0.2.0 is new features and polish.


Breaking change 1: model= is required

Agent(...) used to silently default to EchoModel when model= was omitted. Users got "Echo: ..." output and assumed they were talking to an LLM. v0.2.0 fails fast with a helpful error:

ConfigError: Agent() requires a `model` argument. Pass one of: model='claude-opus-4-7' (Anthropic, needs ANTHROPIC_API_KEY) model='gpt-4o' (OpenAI, needs OPENAI_API_KEY) model='echo' (zero-key fake — text echoes the prompt; for dev/tests) model='mistral-large' (LiteLLM, also: command-, bedrock/, vertex_ai/, ollama/, ...) model=AnthropicModel(...) or any Model-protocol instance for full control.

Migration

If you want…Pass
To talk to Claude (most readers’ real use case)model="claude-opus-4-7"
To talk to GPTmodel="gpt-4o"
To talk to Mistral / Cohere / Bedrock / etc.model="mistral-large" (etc.)
The zero-key fake for tests / devmodel="echo"
Full control over constructionmodel=AnthropicModel("claude-opus-4-7", ...)

Rationale. A default that silently produces plausible-looking but wrong output is hard to debug. The echo behaviour must now be opted into explicitly, so there is no silent fallback.


Breaking change 2: Resolver errors → ConfigError

_resolve_model("totally-unknown-spec") used to raise ValueError. Now it raises ConfigError (from loomflow.core.errors), matching the rest of the configuration-error vocabulary.

- with pytest.raises(ValueError, match="unknown model spec"): - Agent("hi", model="bad-spec") + from loomflow.core.errors import ConfigError + with pytest.raises(ConfigError, match="unknown model spec"): + Agent("hi", model="bad-spec")

If you were catching the resolver error in production code:

try: agent = Agent(prompt, model=user_input_spec) - except ValueError: + except ConfigError: ...

What’s new in 0.2.0 (non-breaking)

Provider coverage

LiteLLMModel. Single adapter for ~100 providers via the LiteLLM SDK. The string resolver dispatches the common prefixes:

Agent("...", model="mistral-large") # → LiteLLMModel Agent("...", model="command-r-plus") # → LiteLLMModel Agent("...", model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0") Agent("...", model="vertex_ai/gemini-pro") Agent("...", model="ollama/llama3") # local Ollama Agent("...", model="groq/llama-3.1-70b") Agent("...", model="litellm/claude-3-haiku") # explicit opt-in

New embedders: VoyageEmbedder, CohereEmbedder. Same shape as OpenAIEmbedder.

Polish

  • Agent.__repr__() for dev-time inspection.
  • RunResult.total_tokens and RunResult.duration properties.
  • agent.consolidate() -> int returns the count of new facts extracted (was None).
  • tools=my_fn. Pass a single callable or Tool directly without list-wrapping. Lists still work.

New plugin API

  • agent.add_tool(fn). Register a tool after construction.
  • agent.remove_tool(name). Unregister by name.
  • agent.tools_list(). List registered tool names.
  • Public introspection properties: agent.model, agent.memory, agent.runtime, agent.tool_host, agent.budget, agent.permissions.
  • agent.recall(query, kind=, limit=). Convenience wrapper around agent.memory.recall(...).

Background work

ConsolidationWorker(memory, interval_seconds=60). Long-running anyio task that periodically calls memory.consolidate(). Surfaces new fact counts via on_consolidated(count) callback; consolidator failures via on_error(exc) so a transient hiccup doesn’t kill the worker. Doubles as an async context manager:

async with ConsolidationWorker(memory, interval_seconds=60): await main() # worker runs in background # Worker is cancelled when the block exits.

Common pitfall: stale install shadowing the editable

If you have a previous pip install loomflow in your env, an editable install (pip install -e .) of 0.2.0 may not take precedence because pip’s regular install sometimes wins on the import path:

$ python -c "import loomflow; print(loomflow.__version__)" 0.1.0 # ← stale; expected 0.2.0

Fix:

pip uninstall loomflow -y pip install -e '.[dev,...]'

Verify with:

python -c "import loomflow; print(loomflow.__version__, loomflow.__file__)" # Should print: 0.2.0 /your/checkout/path/loomflow/__init__.py

This is a Python packaging quirk, not a Loomflow bug. But worth flagging since it produces confusing AttributeError: ... has no attribute 'total_tokens' failures when 0.1’s RunResult is imported instead of 0.2’s.

Last updated on