This repository has been archived on 2026-08-04. You can view files and clone it, but cannot push or open issues or pull requests.
orchestrator/run.py
Adam Moussa ac7101f3df Add memory retriever node (Phase 2)
Plugs the orchestrator into Adam's existing memory store at
~/.claude/projects/-Users-adammoussa-Documents-repositories/memory/. Every
run starts with a top-3 retrieval pass that is then surfaced in the CLI
output and injected as system context into the router and downstream agent.

- retriever.py: load *.md memories (skipping the MEMORY.md index), embed
  with text-embedding-3-small, cache to .cache/embeddings.json keyed on
  file mtime. Cosine similarity, top-k=3 default. Reads only — never
  writes back to the memory store.
- state.py: add `retrieved: list[dict]` to OrchestratorState; relax to
  total=False to match LangGraph's partial-update semantics.
- graph.py: new retriever_node wired as START -> retriever -> router.
  router_node and connector_node now inject retrieved memories into their
  SystemMessage. Retrieval failures are caught and the run continues with
  empty memory context (logged).
- agents.py: make_agent_node injects retrieved memories into each agent's
  system prompt.
- run.py: prints `[retrieved: name1, name2, name3]` (or `[retrieved: none]`)
  before route/result for both --route-only and full-run modes, so bad
  retrieval is visible at a glance.
- .gitignore: add .cache/, .pytest_cache/, .ruff_cache/.

Validated: golden-set still 21/21 passing; smoke tests retrieve plausible
memories ("Send a Slack message to ops about the new exec-aide deploy" ->
project_exec_aide, feedback_exec_aide_vip_management, project_seahaven_slack_bot).
2026-05-15 11:36:03 -04:00

55 lines
1.6 KiB
Python
Executable file

#!/usr/bin/env python3
"""CLI entry point for the orchestration graph.
Usage:
python3 run.py "Write a function that validates emails"
python3 run.py --route-only "Send a Slack message to #general"
"""
import os
import sys
from dotenv import load_dotenv
os.chdir(os.path.dirname(os.path.abspath(__file__)))
load_dotenv(".env")
from graph import app, retriever_node, router_node # noqa: E402 (env must be loaded before graph imports composio)
def _format_retrieved(retrieved: list[dict] | None) -> str:
if not retrieved:
return "[retrieved: none]"
names = ", ".join(m["name"] for m in retrieved)
return f"[retrieved: {names}]"
def main():
if len(sys.argv) < 2 or sys.argv[1] in ("-h", "--help"):
print("Usage: python3 run.py [--route-only] <task description>")
sys.exit(1)
route_only = "--route-only" in sys.argv
args = [a for a in sys.argv[1:] if a != "--route-only"]
task = " ".join(args)
if route_only:
retrieval = retriever_node({"task": task, "messages": []})
retrieved = retrieval.get("retrieved", [])
out = router_node({"task": task, "messages": [], "retrieved": retrieved})
print(_format_retrieved(retrieved))
print(out["route"])
return
result = app.invoke({"task": task, "messages": []})
print(_format_retrieved(result.get("retrieved")))
print(f"[{result['route']}]")
print()
output = result.get("result", "")
if isinstance(output, list):
output = "\n".join(str(c) for c in output)
print(output)
if __name__ == "__main__":
main()