Add AgentCore memory search adapter, remove dead extensions#3
Open
adhajar-amzn wants to merge 18 commits into
Open
Add AgentCore memory search adapter, remove dead extensions#3adhajar-amzn wants to merge 18 commits into
adhajar-amzn wants to merge 18 commits into
Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WebSocket-based channel plugin for nova.amazon.com with credential resolution, inbound message parsing, outbound delivery, onboarding wizard, reconnect with exponential backoff, and heartbeat keepalive. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add required deviceId param to WebSocket URL (server returns 400 without it) - Await sendNovaMessage() in deliver callback to propagate errors - Block all messages when allowlist is empty instead of accepting all - Store reconnect timer and clear on abort to prevent resource leaks - Fix off-by-one in reconnect attempt logging vs delay calculation - Use WebSocket.OPEN class constant consistently in send.ts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
core.config.resolveStorePath does not exist — use
core.channel.session.resolveStorePath(cfg.session?.store, { agentId })
matching the pattern used by Matrix and MSTeams extensions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Python script that sends a message to the bot via the API Gateway Management API and polls the EC2 session transcripts for the response. Supports both direct WS and inject modes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Read NOVA_API_KEY from environment variable instead of embedding the secret in source control. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The deliver callback was reading payload.parts (always empty) instead of
payload.text where the framework actually places the response. The
response frame also lacked a 'to' field, so the server-side Lambda had
no way to resolve the target user's connection. The test script could
only look up connections by connectionId (which changes on reconnect).
- monitor.ts: read payload.text in the deliver callback
- send.ts: include target userId ('to') in the response frame
- test_nova_ws.py: add --user-id flag for stable connection lookups
Also deployed to AWS (not in this repo):
- connect Lambda: stores userId from query string in DynamoDB
- message Lambda: forwards bot responses to the target user's WebSocket
via the API Gateway Management API
- IAM: added execute-api:Invoke to the message Lambda role
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…and unit tests Multi-tenant DynamoDB integration layer (src/hyperion/): - TenantConfigLoader: loads tenant_config + channel links + credentials, assembles OpenClawConfig - HyperionDynamoDBClient: DDB operations for all 4 tables with multi-agent composite keys - HyperionPairingStore: pairing code CRUD with 5-min TTL and retry logic - SessionManager: session key parsing, tenant/agent ID extraction, memory namespacing - UserCredentialStore: KMS envelope encryption for per-user API keys AgentCore ACP extension (extensions/agentcore/): - AgentCoreRuntime: implements OC AcpRuntime interface (ensureSession, runTurn, cancel, close) - Pre-turn: loads tenant context + retrieves memory in parallel - Post-turn: fires memory extraction job (fire-and-forget) - Error classification: throttling, resource not found, service unavailable - Config loader: SSM parameter-based configuration with local override support Hyperion gateway plugin (extensions/hyperion/): - Plugin entry that registers createHyperionPluginService() - Creates AWS SDK clients, calls createHyperionRuntime(), stores as global singleton - Stage resolution from plugin config / HYPERION_STAGE / STACK_NAME Nova channel integration: - monitor.ts loads per-tenant config via getHyperionRuntime() on each inbound message Unit tests (158 tests across 6 files): - Vitest 4.x compatible mocks (regular functions for constructors) - Properly typed test helpers, zero as-any casts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… pairing, tool key mapping - Derive tenant ID from session key via extractTenantId() instead of agent name, preventing cross-tenant collisions when agents share names (P1) - Consume pairing codes atomically with DynamoDB conditional delete to prevent double-redemption race conditions (P1) - Map tool API keys to provider-specific paths (brave_search → search.apiKey, others → search.<provider>.apiKey) instead of overwriting a single key (P1) - Pass gateway base config (ctx.config) into Hyperion runtime so tenant configs inherit global settings like ACP backend selection (P1) - Add endpointOverride to AgentCore config that applies after SSM loading, so runtime ARNs are still discovered when testing with a local endpoint (P2) - Fix env var restoration in credentials test to delete undefined keys instead of setting them to string "undefined" - Update tests for all changes; all 99 tests pass Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ALB forwards IDP user identity via Amz-Mons-Idp-Subject header. No gateway token needed — ALB SG + WAF provide network-level access control. Regenerate bundled provider auth env vars for amazon-nova extension. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tion src/hyperion/ lives in the root workspace but imports @aws-sdk/client-dynamodb, @aws-sdk/client-kms, and @aws-sdk/lib-dynamodb. These were only declared in extensions/hyperion/package.json and not hoisted, causing tsgo failures. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move hyperion lib code into extensions/hyperion/src/lib/ so the extension doesn't depend on src/hyperion/ (which isn't copied to the Docker runtime image). Update all cross-extension imports to use relative sibling paths instead of reaching into src/. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When OPENCLAW_EXTENSIONS is set, remove all other extensions from the runtime-assets stage. This prevents OOM from loading 40+ upstream extensions that aren't needed in our deployment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a message arrives and no ACP session exists for the session key, auto-initialize one before dispatching. This ensures messages route to the AgentCore backend instead of falling through to the embedded Pi agent, which would try to call the model directly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Keep all extensions in the runtime image. The OC config's plugins.allow controls which extensions are loaded at runtime, so physical removal is unnecessary. This fixes startup failures when the config references extensions that were stripped (amazon-nova, memory-core). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add AgentCore-backed memory search adapter replacing OC's built-in SQLite + embedding pipeline, eliminating the need for a local embedding provider (OpenAI, Gemini, etc.) in the container. New: - AgentCoreMemoryManager implementing MemorySearchManager interface - memory-agentcore plugin (kind: "memory") with memory_search/memory_get tools - getAgentCoreConfig() singleton for cross-plugin config sharing Fixed: - runtime.ts SDK types (RetrieveMemoryRecordsCommand, BatchCreateMemoryRecordsCommand) - hyperion extension imports (openclaw/plugin-sdk → openclaw/plugin-sdk/core and /acpx) - runtime.test.ts mock casts (as unknown as ReturnType<...>) - tenant-config-loader.ts null safety and unknown type narrowing - memory-manager.ts inlines OC memory types (no src/ tree imports) - Updated cross-extension import inventory baseline Removed (migrated to extensions/hyperion/ and gateway): - extensions/nova/ — channel plugin migrated to gateway - src/hyperion/ — runtime layer migrated to extensions/hyperion/src/lib/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
adhajar-amzn
commented
Mar 25, 2026
| } | ||
|
|
||
| let memoryNamespacePrefix = DEFAULT_MEMORY_NAMESPACE_PREFIX; | ||
| let memoryId: string | undefined; |
Author
There was a problem hiding this comment.
why is this set to undefined
Addresses PR feedback: explain why memoryId starts as undefined (populated from SSM config JSON, stays undefined if not configured). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
|
Re: config.ts:63 — |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
RetrieveMemoryRecordsCommand, eliminating the need for a local embedding provider (OpenAI, Gemini, etc.) in the containermemory-agentcoreplugin (kind:"memory") registersmemory_search/memory_gettools backed byAgentCoreMemoryManager, with fallback to OC built-in when config unavailableextensions/nova/(migrated to gateway) andsrc/hyperion/(migrated toextensions/hyperion/src/lib/)Changes
New files
extensions/agentcore/src/memory-manager.ts—AgentCoreMemoryManager implements MemorySearchManagerextensions/memory-agentcore/— plugin entry, package.json, plugin manifestModified files
extensions/agentcore/src/runtime.ts— fix SDK types (BatchCreateMemoryRecordsCommand,searchCriteria.searchQuery,memoryRecordSummaries)extensions/agentcore/src/service.ts— exportgetAgentCoreConfig()singletonextensions/agentcore/src/config.ts— parsememoryIdfrom SSM configextensions/agentcore/src/types.ts— addmemoryIdto config typeextensions/hyperion/— fix import paths (openclaw/plugin-sdk→/coreand/acpx)config/openclaw.json5— setplugins.slots.memory: "memory-agentcore"Removed (dead code)
extensions/nova/— 16 files, channel plugin migrated to gatewaysrc/hyperion/— 12 files, runtime layer migrated toextensions/hyperion/src/lib/Test plan
pnpm checkpasses (type check + all lint rules)memoryIdnot configured🤖 Generated with Claude Code