Skip to content

AgentCore Operator Wiring (Plan 3 of 3)#70

Merged
emp3thy merged 19 commits into
mainfrom
worktree-agentcore-plan3
May 30, 2026
Merged

AgentCore Operator Wiring (Plan 3 of 3)#70
emp3thy merged 19 commits into
mainfrom
worktree-agentcore-plan3

Conversation

@emp3thy

@emp3thy emp3thy commented May 30, 2026

Copy link
Copy Markdown
Owner

Summary

Final plan in the AgentCore storage backend trilogy. Adds the operator-facing surface that turns BETTER_MEMORY_STORAGE_BACKEND=agentcore from "hand-craft agentcore.json" into "run better-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), writes agentcore.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)

  • In agentcore mode, fires CreateEvent(role=OTHER) against the current AgentCore session before the existing spool-marker write. Reuses closure_event_payload() and resolve_actor_id() from Plan 2's session.py. Env-var guard fires BEFORE any boto3 import — sqlite-mode pays zero import cost. Failure logs via _error_log.record_hook_error and never propagates. Spool-marker write survives closure-event failure.

Integration test (tests/integration/test_agentcore_roundtrip.py)

  • Gated by BETTER_MEMORY_TEST_AGENTCORE=1. ~3min setup tax (two memory creates). BETTER_MEMORY_TEST_AGENTCORE_KEEP=1 skips teardown for debug. atexit teardown registered BEFORE first create — partial-failure orphans get cleaned up. Stale bm_int_* sweep before fixture. Fast tests (~30s, no extraction wait) + slow gated by _SLOW=1 (extraction wait, ~6min).

Docs

  • README storage-backends section
  • website/configuration.md env-var rows (BETTER_MEMORY_STORAGE_BACKEND, region, test gates)
  • website/agentcore-setup.md (new) — AWS prereqs, IAM policy, init walkthrough
  • website/troubleshooting/agentcore.md (new) — name regex, ~10s lag, x-amz-* system keys, credential discovery, region mismatch, closure-event issues
  • website/mcp-tools.md per-tool agentcore-mode notes
  • website/architecture.md storage-backends section with mermaid diagram

Test plan

  • uv run pytest — 1136 passed, 16 deselected (integration)
  • uv run ruff check (Plan 3 scope) — clean
  • uv run pyright better_memory tests — 0 errors
  • uv run --group docs mkdocs build --strict — clean
  • Real-AWS integration: BETTER_MEMORY_TEST_AGENTCORE=1 uv run pytest -m integration (manual; requires AWS creds, ~3-4min)
  • Manual: better-memory agentcore init end-to-end against fresh AWS account

Spec: docs/superpowers/specs/2026-05-24-agentcore-storage-backend-design.md
Plan: docs/superpowers/plans/2026-05-26-agentcore-cli-stop-hook-docs.md

emp3thy added 18 commits May 27, 2026 08:17

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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.

Comment thread better_memory/cli/agentcore.py Outdated
Comment thread better_memory/cli/agentcore.py Outdated
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.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 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.

@emp3thy
emp3thy merged commit 21ea0f2 into main May 30, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant