feat(integrations): add opt-in SAGE persistent memory hooks#202
Open
l33tdawg wants to merge 1 commit into
Open
feat(integrations): add opt-in SAGE persistent memory hooks#202l33tdawg wants to merge 1 commit into
l33tdawg wants to merge 1 commit into
Conversation
Wire ii-agent into SAGE (Sovereign Agent Governed Experience), a BFT-consensus memory layer for AI agents, via the @hook decorator. - Pre-hook: semantic recall before the model runs; bounded by a strict timeout (SAGE_PRE_HOOK_TIMEOUT_S, default 2s) so a slow/unreachable SAGE node never blocks the agent turn. - Post-hook: stores a concise turn observation; decorated with run_in_background=True so the response returns without waiting for BFT consensus. - Opt-in via SAGE_ENABLED=true; framework runs normally without the sage-agent-sdk extra installed. - Config driven by SAGE_* env vars; no secrets in the source tree. - Uses the async SDK (AsyncSageClient) with lazy init and graceful degradation — any SDK error is logged at debug level and swallowed. - register_sage_hooks() wired into IIAgent.__post_init__; safe no-op when the integration is disabled or the SDK is missing. Files: - src/ii_agent/integrations/sage/{__init__,client,hooks,registrar}.py - src/ii_agent/core/config/sage_config.py - docs/sage_integration.md - src/tests/unit/integrations/test_sage_integration.py (7 tests, including an integration test driving the real AsyncSageClient through respx) - pyproject.toml: new optional extra "sage" pulling sage-agent-sdk>=6.6.1
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
Adds an opt-in integration with SAGE, a BFT-consensus persistent memory layer for AI agents, via the existing
@hookdecorator system. When enabled, each agent turn recalls prior committed memories before the model runs and stores an observation after the turn completes.Disabled by default (
SAGE_ENABLED=false). Framework behavior is unchanged unless the operator setsSAGE_ENABLED=trueand installs the optionalsageextra.Why
ii-agent's memory model today is conversation history + per-session file RAG, which is ephemeral across sessions. For long-running personal agents and multi-agent workflows (both of which ii-agent supports via session forking), there's no mechanism to carry learned context or confidence-scored facts between sessions.
SAGE provides that persistence layer with BFT-validated knowledge (confidence decay, corroboration, reflection loop). This PR wires ii-agent's hook system to SAGE without changing any default behavior, so anyone can try the pairing by flipping one env var.
What's in this PR
src/ii_agent/integrations/sage/- new package:client.py- asyncSageClientwrapper oversage-agent-sdkwithis_available(), recall, proposehooks.py-make_sage_hooks()returns(pre_hook, post_hook); post is decorated withrun_in_background=Trueso the agent response isn't held up by SAGE writesregistrar.py-register_sage_hooks(agent)wires hooks onto anIIAgentinstancesrc/ii_agent/core/config/sage_config.py- env-drivenSageConfigviapydantic-settings(prefixSAGE_)src/ii_agent/agents/agent.py-IIAgent.__post_init__callsregister_sage_hooks(self)inside a try/except (safe no-op when disabled or SDK not installed)docs/sage_integration.md- env vars, registration, fallback semanticspyproject.toml- new optional extra:[project.optional-dependencies].sage = ["sage-agent-sdk>=6.6.1"]src/tests/unit/integrations/test_sage_integration.py- 7 tests, including an end-to-end flow driving the realAsyncSageClientthroughrespxEnv vars
SAGE_ENABLEDfalseSAGE_NODE_URLhttp://localhost:8090SAGE_AGENT_IDSAGE_AGENT_KEYSAGE_DEFAULT_DOMAINii-agentSAGE_RECALL_TOP_K5SAGE_PRE_HOOK_TIMEOUT_S2.0Safety properties
SAGE_ENABLED=false(default) is a pure no-op. The SDK isn't imported, hooks aren't registered, zero runtime cost.pip install ii-agent[sage]installs the SDK. Without it,register_sage_hooksis a try/except no-op.Test plan
python3 -m pytest src/tests/unit/integrations/test_sage_integration.py- 7/7 passingtest_register_sage_hooks_noop_when_disabledtest_register_sage_hooks_appends_two_hooks_when_enabledtest_post_hook_is_marked_run_in_backgroundtest_turn_flow_recalls_then_stores(stubbed SDK)test_pre_hook_respects_timeouttest_pre_hook_noop_when_disabledtest_turn_flow_against_mocked_sdk_http(real SDK + respx wire mock)docker run ghcr.io/l33tdawg/sage:6.6.2).Notes
@hookdecorator surface in ii-agent is a cleaner integration point than the instrumentation patterns I've used in other frameworks - credit where due, this PR is small because the framework's hook system is the right shape.