Skip to content

v0.3.0

Choose a tag to compare

@jin-bo jin-bo released this 29 Apr 11:46
· 145 commits to main since this release

Agentao 0.3.0

Embedded-harness milestone M5 ships and the soft-deprecation cycle
opened in 0.2.16 closes. Agentao(working_directory=) is now a
required keyword argument (the hard break promised in the
0.2.16 DeprecationWarning), MemoryStore and MCPRegistry join
FileSystem / ShellExecutor as injectable capability protocols,
and docs/EMBEDDING.md lands as the single entry point for hosts
choosing between the factory path and pure injection. CLI and ACP
behavior is unchanged because both already route through
agentao.embedding.build_from_environment(...), which absorbs the
new construction shapes internally.

Highlights

  • MemoryStore capability protocol (Issue #16). Embedded hosts
    can now swap the memory backend — Redis, Postgres, in-process
    dict, remote API — without subclassing or forking
    MemoryManager. The SQLiteMemoryStore default is unchanged and
    remains the CLI / ACP backing store. Two strict-vs-graceful
    classmethods make the asymmetry explicit at every call site:
    SQLiteMemoryStore.open(path) (creates the parent dir,
    propagates OSError / sqlite3.Error — used for the user-scope
    store where a failure should disable the scope) and
    SQLiteMemoryStore.open_or_memory(path) (degrades to :memory:
    on the same errors — used for the project-scope store where a
    missing DB is preferable to a crashed agent). The :memory:
    fallback moved out of MemoryManager.__init__ into the store
    classmethod, so the manager is now storage-agnostic and does not
    import sqlite3.

  • MCPRegistry capability protocol (Issue #17). Embedded hosts
    can now enumerate MCP servers from any source — in-process
    dict, plugin system, dynamic discovery, remote registry —
    without writing to .agentao/mcp.json. Two default
    implementations ship in agentao.mcp.registry:
    FileBackedMCPRegistry (CLI / ACP default — reads
    <wd>/.agentao/mcp.json + ~/.agentao/mcp.json,
    byte-equivalent to the pre-Protocol behavior) and
    InMemoryMCPRegistry (programmatic counterpart for hosts and
    tests). Agentao(mcp_registry=...) is mutually exclusive with
    mcp_manager= (the registry is the config source for
    construction; the manager is the pre-built construction
    outcome
    ). Bare Agentao(working_directory=...) outside the
    factory still falls back to load_mcp_config so existing
    CLI-shaped scripts keep working.

  • docs/EMBEDDING.md (Issue #18). Single canonical guide for
    embedded hosts choosing between
    agentao.embedding.build_from_environment(...) (the factory
    path — implicit .env / .agentao/ / cwd / home reads), pure
    injection (Agentao(...) with explicit llm_client=,
    memory_manager=, mcp_registry=, …, no implicit reads), and
    partial capability injection (mix the factory with a custom
    filesystem= / shell= / memory_store=). Includes async
    patterns (await agent.arun(...)), opt-in subsystem patterns
    (replay_config=, sandbox_policy=, bg_store=), and a
    pre-0.3.0 migration guide. Bundled examples
    (examples/data-workbench, examples/batch-scheduler,
    examples/ticket-automation, examples/saas-assistant) were
    silently broken since the 0.2.16 factory cut and now route
    through build_from_environment(...).

  • Agentao(working_directory=) is required. The
    Path.cwd() lazy fallback is gone; the property returns the
    frozen value unconditionally. Two Agentao instances created
    with different working_directory values report independent
    paths even in the same process; an os.chdir inside the host
    has no effect on an already-constructed Agentao. CLI and
    ACP behavior is unchanged because both already route through
    the factory, which always passes an explicit
    working_directory=.

Tests

  • tests/test_memory_store_swap.py (new) — pins the
    MemoryStore Protocol contract with an InMemoryMemoryStore
    fake covering all 15 methods. Asserts the manager routes
    through the fake and never touches sqlite3.connect when an
    injected store is provided.
  • tests/test_mcp_registry_swap.py (new) — covers
    FileBackedMCPRegistry / InMemoryMCPRegistry correctness,
    manager routing, and factory wiring. Includes a recording
    fake that asserts list_servers() is consulted before
    load_mcp_config.
  • tests/test_memory_decoupling.py — guards the invariant that
    import agentao.memory never transitively pulls
    agentao.mcp / the MCP SDK. The Issue #17 wiring originally
    broke this (agentao.memory.__init__ re-exporting
    MemoryStore from agentao.capabilities started loading
    agentao.mcp.registry); fixed by demoting MemoryStore's
    canonical home to agentao.capabilities only.
  • Existing suites stay green: 2111 passing on the post-#17
    baseline, no regressions from the version-bump cut.

Migration (from 0.2.16)

MemoryManager no longer accepts project_root= / global_root=:

# before:
mgr = MemoryManager(project_root=p, global_root=g)
# after:
mgr = MemoryManager(
    project_store=SQLiteMemoryStore.open_or_memory(p / "memory.db"),
    user_store=SQLiteMemoryStore.open(g / "memory.db") if g else None,
)

MemoryStore is no longer re-exported from agentao.memory:

# before:
from agentao.memory import MemoryStore
# after:
from agentao.capabilities import MemoryStore

Agentao() without working_directory= now raises TypeError:

# before (deprecated in 0.2.16):
agent = Agentao()
# after:
agent = Agentao(working_directory=Path.cwd())
# or, for CLI-style env / disk auto-detection:
from agentao.embedding import build_from_environment
agent = build_from_environment(working_directory=Path.cwd())

CLI and ACP users see no change because both already route through
the factory.

Release Summary

  • Version: 0.3.0
  • Git tag: v0.3.0
  • GitHub release type: regular release, not pre-release
  • Publish workflow: .github/workflows/publish.yml

Install

pip install -U agentao

Maintainer Checklist

  1. Confirm agentao/__init__.py reports 0.3.0 (drop the .dev0
    suffix from 0.3.0.dev0).

  2. Run the smoke path:
    uv run python -m pytest tests/ && uv build && uv run twine check dist/*.

  3. Push the tag:

    git push origin v0.3.0
  4. Create the GitHub release for v0.3.0.

  5. Leave Set as a pre-release unchecked so
    .github/workflows/publish.yml publishes to PyPI (the workflow's
    tag-vs-package version consistency check will validate alignment
    before upload).

  6. Close GitHub issues #14 (hard break — working_directory=
    required), #16 (MemoryStore Protocol), #17 (MCPRegistry
    Protocol), and #18 (docs/EMBEDDING.md + example sweep) once the
    release is on PyPI.

Full Changelog

See CHANGELOG.md for the 0.3.0 entry.