Skip to content

feat: add selective subagent memory context - #479

Merged
wey-gu merged 2 commits into
mainfrom
agent/selective-subagent-memory-context
Aug 8, 2026
Merged

feat: add selective subagent memory context#479
wey-gu merged 2 commits into
mainfrom
agent/selective-subagent-memory-context

Conversation

@hawkingrei

@hawkingrei hawkingrei commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add native SubagentStart bootstrap hooks for Claude Code and Codex.
  • Select full Context Bundle injection, retrieval routing only, or no-op behavior from an exact, case-sensitive NMEM_SUBAGENT_CONTEXT_TYPES allowlist.
  • Bound complete subagent context to 4 KiB with short timeouts and fail-open behavior.
  • Preserve the configured Nowledge AI Identity and prevent speculative subagent findings from being distilled automatically.

Motivation

Non-fork subagents run with isolated context, so they cannot rely on the parent session's injected Context Bundle. Loading the complete bundle for every small exploration or implementation task would add latency, token cost, and attention noise. This change provides a role-aware bootstrap while keeping simple agents lightweight.

Implementation

Claude Code

  • Full context defaults to Plan,code-reviewer,architect,researcher.
  • Explore is a no-op by default.
  • Other unlisted agent types receive retrieval routing without a context read.

Codex

  • Full context defaults to custom roles planner,code-reviewer,architect,researcher.
  • Built-in explorer is a no-op by default.
  • Built-in default and worker receive retrieval routing without a context read.
  • The hook uses Codex agent_type role values and enables the packaged hook state during setup.

Setting NMEM_SUBAGENT_CONTEXT_TYPES replaces the host default. An empty value disables full Context Bundle injection while retaining routing for non-explorer roles.

User impact

Context-heavy planning, review, architecture, and research subagents start with bounded cross-tool context. Simple exploration and execution agents avoid unnecessary Mem reads while retaining an explicit path to search prior decisions when the task requires it.

Validation

  • Targeted Claude Code subagent and lifecycle hook tests
  • Targeted Codex hook, installer, timeout, fail-open, and UTF-8 boundary tests
  • Cross-plugin static integration contract
  • Codex plugin validator
  • JSON, Python syntax, and git diff --check validation

Related issues

N/A

Summary by CodeRabbit

  • New Features

    • Added subagent startup context support for Claude Code and Codex.
    • Provides role-based context injection, targeted retrieval guidance, and configurable subagent type filtering.
    • Limits injected context to 4 KiB and safely handles unavailable or malformed context.
    • Added support for disabling or customizing context behavior through environment settings.
  • Documentation

    • Updated setup guides, troubleshooting instructions, behavioral guidance, and changelogs.
  • Bug Fixes

    • Improved UTF-8-safe truncation, timeout handling, fail-open behavior, and explorer-specific handling.
  • Chores

    • Updated plugin versions: Claude Code to 0.7.22 and Codex to 0.1.30.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Claude Code and Codex now support SubagentStart hooks. The hooks route bounded Nowledge context by agent type, support environment overrides, preserve fallback guidance, skip configured explorer roles, and update packaging, documentation, validation, and tests.

Changes

SubagentStart context delivery

Layer / File(s) Summary
Claude Code subagent routing
shared/behavioral-guidance.md, nowledge-mem-claude-code-plugin/...
Claude Code adds role-based SubagentStart handling with bounded UTF-8 context, routing guidance, environment-based allowlists, Explore suppression, and fail-open behavior.
Codex subagent routing
nowledge-mem-codex-plugin/...
Codex adds role-based startup context, timeout controls, bounded UTF-8 output, explorer suppression, routing-only behavior, installer state, validation, and tests.
Release and integration contracts
.claude-plugin/marketplace.json, integrations.json, tests/plugin_e2e/test_key_plugins_e2e.py, nowledge-mem-claude-code-plugin/.claude-plugin/plugin.json, nowledge-mem-codex-plugin/.codex-plugin/plugin.json
Plugin versions, integration metadata, hook requirements, documentation, and end-to-end contract checks reflect the new hooks.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SubagentRuntime
  participant ContextHook
  participant NowledgeContext
  SubagentRuntime->>ContextHook: SubagentStart payload
  ContextHook->>NowledgeContext: Load bounded context for eligible role
  NowledgeContext-->>ContextHook: Context or failure
  ContextHook-->>SubagentRuntime: Routing guidance or additionalContext
Loading

Possibly related PRs

Suggested reviewers: wey-gu

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: selective subagent memory context support.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/selective-subagent-memory-context

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@hawkingrei
hawkingrei marked this pull request as ready for review August 8, 2026 02:30

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@nowledge-mem-claude-code-plugin/tests/test_nmem_hook_subagent.py`:
- Around line 31-51: Isolate the default-policy tests, including
test_selected_subagent_injects_bounded_context_and_boundary and the referenced
tests, from the process environment by removing NMEM_SUBAGENT_CONTEXT_TYPES
before loading the module. Use a scoped fixture or per-test environment cleanup
so each test consistently exercises the module’s default context-type policy.

In `@nowledge-mem-codex-plugin/hooks/nmem-context.py`:
- Line 254: Update the SystemExit statement in the exception-handling flow of
nmem-context.py to explicitly suppress the active exception context by raising
it from None, preserving the existing fail-open exit status.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 098aff85-61a1-4a8c-9136-c5ef8f7c2c3f

📥 Commits

Reviewing files that changed from the base of the PR and between 7e23db7 and 5307ac3.

📒 Files selected for processing (19)
  • .claude-plugin/marketplace.json
  • integrations.json
  • nowledge-mem-claude-code-plugin/.claude-plugin/plugin.json
  • nowledge-mem-claude-code-plugin/CHANGELOG.md
  • nowledge-mem-claude-code-plugin/README.md
  • nowledge-mem-claude-code-plugin/hooks/hooks.json
  • nowledge-mem-claude-code-plugin/scripts/nmem-hook-subagent.py
  • nowledge-mem-claude-code-plugin/tests/test_nmem_hook_subagent.py
  • nowledge-mem-codex-plugin/.codex-plugin/plugin.json
  • nowledge-mem-codex-plugin/AGENTS.md
  • nowledge-mem-codex-plugin/CHANGELOG.md
  • nowledge-mem-codex-plugin/README.md
  • nowledge-mem-codex-plugin/hooks/hooks.json
  • nowledge-mem-codex-plugin/hooks/nmem-context.py
  • nowledge-mem-codex-plugin/scripts/install_hooks.py
  • nowledge-mem-codex-plugin/scripts/validate-plugin.mjs
  • nowledge-mem-codex-plugin/tests/test_codex_plugin.py
  • shared/behavioral-guidance.md
  • tests/plugin_e2e/test_key_plugins_e2e.py

Comment on lines +31 to +51
def test_selected_subagent_injects_bounded_context_and_boundary():
module = _load_module()
stdout = io.StringIO()
oversized_context = "context-内容\n" * 1000

with mock.patch.object(module, "_load_context", return_value=oversized_context), \
mock.patch.object(module.sys, "stdout", stdout):
assert module.main(
{"hook_event_name": "SubagentStart", "agent_type": "Plan"}
) == 0

output = json.loads(stdout.getvalue())["hookSpecificOutput"]
additional_context = output["additionalContext"]
assert output["hookEventName"] == "SubagentStart"
assert "isolated subagent context" in additional_context
assert "memory_search` / `thread_search" in additional_context
assert "nmem --json m search" in additional_context
assert "Do not distill speculative" in additional_context
assert "Current Nowledge context" in additional_context
assert "context truncated for subagent" in additional_context
assert len(additional_context.encode("utf-8")) <= module.SUBAGENT_CONTEXT_MAX_BYTES

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Isolate NMEM_SUBAGENT_CONTEXT_TYPES in tests that require defaults.

These tests read the real process environment. If the test runner sets NMEM_SUBAGENT_CONTEXT_TYPES, the default-policy assertions can fail or test a different policy.

Clear this variable for each default-policy test, or add an autouse fixture that removes it before loading the module.

Also applies to: 54-69, 71-87, 89-101, 103-120

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@nowledge-mem-claude-code-plugin/tests/test_nmem_hook_subagent.py` around
lines 31 - 51, Isolate the default-policy tests, including
test_selected_subagent_injects_bounded_context_and_boundary and the referenced
tests, from the process environment by removing NMEM_SUBAGENT_CONTEXT_TYPES
before loading the module. Use a scoped fixture or per-test environment cleanup
so each test consistently exercises the module’s default context-type policy.

agent_type == "explorer"
and agent_type not in _subagent_context_types()
):
raise SystemExit(0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Suppress the handled exception before exiting.

Line 254 raises SystemExit while another exception is active. Add from None so the intentional fail-open exit does not retain an exception chain. This resolves Ruff B904.

Proposed fix
-                raise SystemExit(0)
+                raise SystemExit(0) from None
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
raise SystemExit(0)
raise SystemExit(0) from None
🧰 Tools
🪛 Ruff (0.16.1)

[warning] 254-254: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@nowledge-mem-codex-plugin/hooks/nmem-context.py` at line 254, Update the
SystemExit statement in the exception-handling flow of nmem-context.py to
explicitly suppress the active exception context by raising it from None,
preserving the existing fail-open exit status.

Source: Linters/SAST tools

@wey-gu
wey-gu merged commit 96c83b6 into main Aug 8, 2026
5 checks passed
@wey-gu

wey-gu commented Aug 8, 2026

Copy link
Copy Markdown
Member

Thanks @hawkingrei, merged. I kept the shape of the contribution and added a focused cleanup pass: subagent hook tests now isolate their env defaults, and the Codex hook fail-open path exits cleanly without noisy chained exceptions. The Claude/Codex targeted tests and Codex plugin validator are green.

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.

2 participants