v0.3.1
Agentao 0.3.1
Lands the embedded harness contract — the stable host-facing
API surface for embedding Agentao inside another application. Hosts
can now subscribe to a typed event stream, read a JSON-safe snapshot
of the active permission policy, and rely on checked-in JSON schema
snapshots that protect both the public events and the ACP payloads
across releases. This is an Added-only patch in the 0.3.x
series; no required code change to upgrade from 0.3.0. CLI and ACP
behavior is unchanged because both consume the same public surface.
Highlights
-
agentao.harnesspublic package — the host-facing
compatibility boundary. ExportsActivePermissions,
ToolLifecycleEvent,SubagentLifecycleEvent,
PermissionDecisionEvent,HarnessEvent(discriminated union),
EventStream,StreamSubscribeError,RFC3339UTCString, and
the schema export helpers. Internal runtime types
(AgentEvent,ToolExecutionResult,PermissionEngine) are
deliberately not re-exported — the harness package is the
version-stable boundary. Hosts that target onlyagentao.harness
(plus theAgentao(...)constructor and the two methods below)
stay forward-compatible across releases. -
Agentao.events(session_id=None)— async iterator over
HarnessEvent. No replay; bounded backpressure; same-session
ordering guaranteed;PermissionDecisionEventprecedes
ToolLifecycleEvent(phase="started")for the same
tool_call_id. MVP supports one consumer perAgentao
instance. Public events deliberately omit raw tool args, raw
stdout/stderr, raw diffs, and MCP raw responses — only
redacted/truncatedsummary/task_summary/reasonstrings
reach hosts. -
Agentao.active_permissions()— JSON-safe snapshot of the
active policy (mode,rules,loaded_sources). Cached; the
cache invalidates onset_mode()and onadd_loaded_source(...)
with a new label.loaded_sourcescarries stable string labels
(preset:<mode>,project:<path>,user:<path>,
injected:<name>); MVP intentionally does not expose per-rule
provenance — hosts that need it combineloaded_sourceswith
their own injected metadata. -
Schema snapshots and CI drift check — every release ships
checked-in JSON schema snapshots
(docs/schema/harness.events.v1.json,
docs/schema/harness.acp.v1.json). Generated from the Pydantic
models and byte-equality-checked by
tests/test_harness_schema.pyandtests/test_acp_schema.py. A
new fast-fail step in CI Job 0
(scripts/write_harness_schema.py --check) catches drift before
the test matrix runs. -
Three public lifecycle event families —
ToolLifecycleEvent,
SubagentLifecycleEvent,PermissionDecisionEvent. Tool
cancellation surfaces asphase="failed", outcome="cancelled"; sub-agent cancellation surfaces as a
distinctphase="cancelled"(lineage tracking benefits from the
explicit phase).PermissionDecisionEventfires on every
decision —allow,deny, orprompt— not only on
deny/prompt; consumers that don't render allow events still must
drain the iterator to avoid backpressure. -
CLI as the first host —
cli /statusnow reads the
permission-mode banner fromagent.active_permissions()and
displaysloaded_sourcesfor transparency. The CLI consumes the
same public surface external embedders use; future hosts inherit
the same behavior.
Tests
2229 passing on the post-release baseline (no regressions from
0.3.0). New harness-specific suites:
tests/test_harness_schema.py— byte-equality drift check
betweendocs/schema/harness.events.v1.jsonand the generator
output; discriminated-union validation; RFC 3339 UTC timestamp
acceptance/rejection (canonicalZonly,+00:00rejected).tests/test_acp_schema.py— same byte-equality check for
docs/schema/harness.acp.v1.jsonplus payload coverage.tests/test_active_permissions.py— project-only / user+project
/ preset-only / injected / no-engine fallback paths; cache
invalidation; JSON-safety.tests/test_harness_event_stream.py— ordering, no-subscriber
drop, mid-turn subscription, bounded backpressure, cancellation
cleanup,StreamSubscribeErroron duplicate subscribe.tests/test_harness_tool_events.py— sync + AsyncTool lifecycle;
raw args/output not leaked; stableerror_typeidentifiers;
cancellation underphase="failed", outcome="cancelled".tests/test_harness_permission_events.py— allow/deny/prompt
fan-out;decision_iduniqueness; ordering vs tool lifecycle.tests/test_harness_subagent_events.py— spawn-and-terminal
pairing;cancelledphase; redactedtask_summary.tests/test_cli_harness_events.py— CLI rendering of public
lifecycle events.
Companion fix: tests/test_outbound_sanitize.py adds
TestNormalizeToolCallsMissingId to lock the
missing-tool-call-id regression (see Changed below).
Upgrade (from 0.3.0)
0.3.1 is strictly backwards-compatible. No required code
change. Existing calls into Agentao(...),
build_from_environment(...), capability protocols, and the
transport layer keep working.
What's available to opt into:
from agentao.harness import (
ToolLifecycleEvent,
PermissionDecisionEvent,
SubagentLifecycleEvent,
)
# Subscribe to lifecycle events
async for ev in agent.events():
if isinstance(ev, ToolLifecycleEvent):
...
# Read the active policy snapshot
snap = agent.active_permissions()
print(snap.mode, snap.loaded_sources)A runnable end-to-end demo lives at examples/harness_events.py.
The full embedding walkthrough is in docs/EMBEDDING.md §7
"Host-facing harness contract"; the API reference is at
docs/api/harness.md.
New dependency. pydantic>=2 is now a direct dependency. If
your environment pins Pydantic v1, lift the pin before upgrading.
What stays internal. agentao.transport.AgentEvent /
Transport.emit(...), agentao.runtime.identity.*, and
agentao.harness.projection.* are not part of the host-facing
contract and may change in any release. Production hosts should
target agentao.harness only.
SemVer note
0.3.1 is an Added-only patch — the 0.3.x series treats
additive public surfaces as patch-eligible during pre-1.0. Strict
SemVer consumers should read it as equivalent to a minor bump.
There are no removed fields, no renamed enum values, and no
changed semantics on existing surfaces.
Release Summary
- Version:
0.3.1 - Git tag:
v0.3.1 - GitHub release type: regular release, not pre-release
- Publish workflow:
.github/workflows/publish.yml
Install
pip install -U agentaoMaintainer Checklist
- Confirm
agentao/__init__.pyreports0.3.1(drop the.dev0
suffix from0.3.1.dev0). - Run the smoke path:
uv run python -m pytest tests/ \ && uv run python scripts/write_harness_schema.py --check \ && uv run python scripts/write_replay_schema.py --check \ && uv build \ && uv run twine check dist/*
- Push the tag:
git push origin v0.3.1
- Create the GitHub release for
v0.3.1. - Leave Set as a pre-release unchecked so
.github/workflows/publish.ymlpublishes to PyPI (the workflow's
tag-vs-package version consistency check will validate alignment
before upload).
Full Changelog
See CHANGELOG.md for the 0.3.1 entry.