Skip to content

feat: directive recall + pre-tool-use hook#11

Open
felix-xtrace wants to merge 2 commits into
mainfrom
fm-feat/directive-recall
Open

feat: directive recall + pre-tool-use hook#11
felix-xtrace wants to merge 2 commits into
mainfrom
fm-feat/directive-recall

Conversation

@felix-xtrace

Copy link
Copy Markdown

What

Adds the @xtraceai/memory surface for procedural-memory directive recall — the read side of the directive loop now live on the VecDB memory API. An agent can recall the situated lesson/procedure directives keyed to what it's about to touch, and the AI SDK integration fires it automatically before each tool call.

API

// 1. Typed method
const { data, context } = await client.memories.recallDirectives({
  action: { tool: "Edit", args: { file_path: "tool_loop.py" } }, // the in-flight call
  user_id: "alice",
  mode: "retrieve",            // fast stage-1 tripwire (default); "compose" = + LLM gate
});

// 2. AI SDK pre-tool-use hook — recall fires before each tool runs, injected into the result
import { withDirectiveRecall } from "@xtraceai/memory/ai-sdk";
streamText({
  model: openai("gpt-4o-mini"),
  tools: withDirectiveRecall(myTools, { client, user_id: "alice" }),
  messages,
});
  • memories.recallDirectives({ action | entities, task, mode }) — sugar over POST /v1/memories/search with include:[lesson,procedure]. Defaults mode:"retrieve" (the right lane for a per-tool-call hook). A client-side firing-rule guard throws if neither a non-empty action nor entities is given (mirrors the server's 422 — directives fire on symbols, not a query).
  • renderDirectivesPrompt(directives) — deterministic inject-ready markdown (for retrieve, where the server doesn't pre-render).
  • withDirectiveRecall(tools, opts) (ai-sdk) — wraps a tools object so each tool's {name, args} recalls its directives before it runs and prepends them to the result; directiveContextForToolCall() is the underlying primitive. Fails soft — a recall hiccup never breaks a tool; tools without execute pass through.
  • Types: ActionContext, DirectiveDetails, DirectiveMemory, DirectiveListEnvelope, RecallDirectivesParams — self-contained, so the core Memory discriminated union and its render path are untouched.

Tests

7 new (src/directives.test.ts): body shape + retrieve default, the firing-rule guard (incl. fieldless action), explicit-entities + compose + task, render output, and the AI SDK wrapper (recall-before-exec + inject + pass-through + fail-soft). typecheck + full suite (53) + build all green.

Note on the branch

Built on main (the hand-written SDK) for the fast path. The repo has a Stainless-generated next (v0.2.0) line in flight; when that lands, the directive types should flow from the OpenAPI spec (which the API already emits) and the recallDirectives sugar + ai-sdk hook re-port as hand layers on top.

🤖 Generated with Claude Code

felix-xtrace and others added 2 commits June 26, 2026 10:47
SDK surface for procedural-memory directive recall (the VecDB recall route):

- types: ActionContext, DirectiveDetails, DirectiveMemory, DirectiveListEnvelope,
  RecallDirectivesParams — self-contained, no change to the core Memory union.
- memories.recallDirectives({ action | entities, task, mode }): typed sugar over
  POST /v1/memories/search with include:[lesson,procedure]; defaults mode="retrieve"
  (fast stage-1 lane). Client-side firing-rule guard throws if neither a non-empty
  action nor entities is given (mirrors the server 422).
- renderDirectivesPrompt(): deterministic inject-ready markdown.
- ai-sdk: withDirectiveRecall(tools, opts) — a pre-tool-call hook that recalls the
  directives for each tool's {name,args} before it runs and prepends them to the
  result; directiveContextForToolCall() primitive. Fails soft.

7 tests; typecheck + full suite (53) + build green. Built on main (hand-written SDK);
re-port to the Stainless `next` line when that lands.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
examples/agent_loop_demo.ts runs the same task (make the judge model configurable in
scripts/memory_quality_sweep.py) through a Vercel AI SDK loop twice — plain tools vs
withDirectiveRecall. With recall, the captured lesson ("thread judge_model through the
scoring path instead of hardcoding JUDGE_MODEL") fires on read_file and the agent adopts the
team convention (judge_model); without it, the agent uses a generic `model` param. Reads all
creds from env (no hard-coded paths). Adds @ai-sdk/openai as a dev dependency for the example.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant