Lifecycle Hooks¶
OMPA provides 5 lifecycle hooks that wrap your agent's natural event loop. Each hook has a token budget — the maximum context it injects into your agent.
Hook overview¶
| Hook | Token Budget | Fires When |
|---|---|---|
session_start |
~2,000 | Session begins |
user_message |
~100 | Each user message arrives |
post_tool |
~200 | After each tool call |
pre_compact |
~100 | Before context compaction |
stop |
~500 | Session ends |
Wiring hooks into your agent¶
Python API¶
from ompa import Ompa
ao = Ompa(vault_path="./workspace")
# 1. At session start — inject memory context
result = ao.session_start()
system_prompt = result.output # ~2K tokens — add to your system prompt
# 2. On each user message
for message in user_messages:
hint = ao.handle_message(message)
# hint.output contains routing guidance (~100 tokens)
# 3. After each tool call
ao.post_tool("write", {"file_path": "work/active/auth.md"})
# 4. Before context compaction (if your agent supports it)
ao.pre_compact(current_transcript)
# 5. At session end
ao.stop()
Claude Code hooks (CLAUDE.md)¶
## Hooks
- session_start: Run `python -c "from ompa import Ompa; ao=Ompa('./workspace'); print(ao.session_start().output)"`
- stop: Run `python -c "from ompa import Ompa; ao=Ompa('./workspace'); ao.stop()"`
OpenClaw integration¶
from ompa import Ompa
class OmpaMemoryPlugin:
def __init__(self, vault_path: str):
self.ao = Ompa(vault_path)
def on_session_start(self) -> str:
return self.ao.session_start().output
def on_message(self, message: str) -> str:
return self.ao.handle_message(message).output
def on_tool_use(self, tool_name: str, tool_input: dict) -> None:
self.ao.post_tool(tool_name, tool_input)
def on_stop(self) -> str:
return self.ao.stop().output
Custom hooks¶
You can register your own hooks alongside the built-in ones:
from ompa.hooks import Hook, HookContext, HookResult
from ompa import Ompa
class SlackNotifyHook(Hook):
def __init__(self):
super().__init__("slack_notify", token_budget=0)
def execute(self, context: HookContext, **kwargs) -> HookResult:
# Post to Slack on session end
send_slack_message(f"Session ended: {context.vault_path}")
return HookResult(hook_name=self.name, success=True, output="", tokens_hint=0)
ao = Ompa("./workspace")
ao.hooks.register_hook("stop", SlackNotifyHook())
What session_start injects¶
The session_start hook assembles context from all three layers:
- Vault listing — top-level note names and recent modifications
- North Star — contents of
brain/north-star.md(your persistent goals) - Active work — notes in
work/active/ - Palace wings — list of all wings and their rooms
- KG stats — entity count, recent triples
Total output is capped at approximately 2,000 tokens.
What post_tool does automatically¶
When a tool call writes or edits a markdown file, post_tool automatically:
- Adds the file to the palace metadata layer
- Extracts entities and wikilinks into the knowledge graph
- Updates the semantic search index (if built)
This keeps all three layers in sync without manual intervention.