AgentCore Operator Wiring (Plan 3 of 3)#70
Conversation
…n up on partial failure
# Conflicts: # website/configuration.md
There was a problem hiding this comment.
🔴 Claude BugBot Analysis
Found 2 potential bugs in this PR.
medium: 1 | low: 1
One medium-severity resource leak: AWS memory resources created by create_memory can be orphaned if _poll_until_active subsequently raises, because the orphan-cleanup guard at line 251 relies on the Python variable assignment rather than on AWS resource creation. One low-severity unguarded index access in the smoke handler that produces an opaque error message on empty successfulRecords.
Round-1 BugBot findings on PR #70: - MEDIUM: _create_one_memory leaked AWS resource if _poll_until_active raised after create_memory succeeded (FAILED state OR 240s timeout). Refactor: pass a mutable created_ids: list[str] into _create_one_memory; helper appends raw memory_id immediately after create_memory returns, BEFORE polling. Caller iterates the list on exception and deletes every id — covers both "create #2 raised" AND "create #1 succeeded but polling raised". Add test_init_deletes_orphan_when_poll_raises_after_create. - LOW: _handle_smoke indexed create_resp["successfulRecords"][0] after only checking failedRecords. Empty successfulRecords (legal AWS edge) would raise IndexError which the outer try/except converted to rc=1 with the unhelpful message "list index out of range". Add explicit guard with descriptive RuntimeError before the index access. 8 init tests + 3 smoke tests pass.
There was a problem hiding this comment.
🟢 Claude BugBot Analysis
Both previously reported bugs have been fixed in this PR. No new bugs were found in the added or modified code. The orphan-cleanup leak (PRRT_kwDOSGIXI86F5S1h) is addressed by threading a created_ids: list[str] into _create_one_memory, which appends the raw AWS memory ID immediately after create_memory returns — before _poll_until_active is called — so the caller's except block can delete the resource even when polling raises. The unguarded index access on successfulRecords (PRRT_kwDOSGIXI86F5S1j) is resolved by guarding with if not successful: raise RuntimeError(...) before the [0] dereference in _handle_smoke.
No bugs were detected in this PR.
Summary
Final plan in the AgentCore storage backend trilogy. Adds the operator-facing surface that turns
BETTER_MEMORY_STORAGE_BACKEND=agentcorefrom "hand-craft agentcore.json" into "runbetter-memory agentcore init, follow the docs, done."Plan 1 (Protocol + sqlite) merged via #67.
Plan 2 (AgentCoreBackend boto3 impl + factory) merged via #68 at
390b1f5.Plan 3 (this PR) — CLI + Stop-hook + integration tests + docs.
What's in here
CLI (
better-memory agentcore ...)init— creates both AWS Bedrock AgentCore memories (semantic + episodic), polls until ACTIVE (240s timeout), writesagentcore.json. Pre-flight name check for BOTH default names. Partial-failure cleanup deletes orphan episodic if semantic create fails. ValidationException maps to friendly stderr.status— GetMemory on both, prints state. Exit 0 iff both ACTIVE.smoke— observe → list_events → batch_create → list_records → batch_delete cycle against existing memories. Ops verification.migrate-from-sqlite— stub raising NotImplementedError with deferred-spec pointer.Stop hook (
better_memory/hooks/session_close.py)CreateEvent(role=OTHER)against the current AgentCore session before the existing spool-marker write. Reusesclosure_event_payload()andresolve_actor_id()from Plan 2'ssession.py. Env-var guard fires BEFORE any boto3 import — sqlite-mode pays zero import cost. Failure logs via_error_log.record_hook_errorand never propagates. Spool-marker write survives closure-event failure.Integration test (
tests/integration/test_agentcore_roundtrip.py)BETTER_MEMORY_TEST_AGENTCORE=1. ~3min setup tax (two memory creates).BETTER_MEMORY_TEST_AGENTCORE_KEEP=1skips teardown for debug. atexit teardown registered BEFORE first create — partial-failure orphans get cleaned up. Stalebm_int_*sweep before fixture. Fast tests (~30s, no extraction wait) + slow gated by_SLOW=1(extraction wait, ~6min).Docs
website/configuration.mdenv-var rows (BETTER_MEMORY_STORAGE_BACKEND, region, test gates)website/agentcore-setup.md(new) — AWS prereqs, IAM policy, init walkthroughwebsite/troubleshooting/agentcore.md(new) — name regex, ~10s lag, x-amz-* system keys, credential discovery, region mismatch, closure-event issueswebsite/mcp-tools.mdper-tool agentcore-mode noteswebsite/architecture.mdstorage-backends section with mermaid diagramTest plan
uv run pytest— 1136 passed, 16 deselected (integration)uv run ruff check(Plan 3 scope) — cleanuv run pyright better_memory tests— 0 errorsuv run --group docs mkdocs build --strict— cleanBETTER_MEMORY_TEST_AGENTCORE=1 uv run pytest -m integration(manual; requires AWS creds, ~3-4min)better-memory agentcore initend-to-end against fresh AWS accountSpec:
docs/superpowers/specs/2026-05-24-agentcore-storage-backend-design.mdPlan:
docs/superpowers/plans/2026-05-26-agentcore-cli-stop-hook-docs.md