← Back to PRs

#9677: feat: expose incomingMessage in bootstrap hook context

by speedbal open 2026-02-05 15:19 View on GitHub →
agents stale
Summary Expose the user's incoming message text to agent:bootstrap hooks via a new optional incomingMessage field on AgentBootstrapHookContext. Motivation Bootstrap hooks can currently mutate bootstrapFiles and access session metadata (sessionKey, sessionId, agentId), but they have no visibility into what the user actually said. This limits hooks to static operations — they can't tailor their behavior based on the current message. Use case: semantic memory injection With incomingMessage available, a bootstrap hook can: ``` registerInternalHook("agent:bootstrap", async (event) => { const ctx = event.context as AgentBootstrapHookContext; if (!ctx.incomingMessage) return; // Search semantic memory based on what the user asked const relevantFacts = await searchMemory(ctx.incomingMessage); // Inject as a context file so the agent sees them ctx.bootstrapFiles.push({ name: "MEMORY_CONTEXT.md", path: "/dynamic", content: relevantFacts.map(f => `- ${f.text}`).join("\n"), missing: false, }); }); ``` This enables agents with persistent memory systems to automatically inject relevant context every turn — without explicitly calling a tool. Other use cases • Message-aware file filtering: Only load certain bootstrap files when the user mentions specific topics • Dynamic system prompt augmentation: Prepend context relevant to the user's question • Analytics/logging: Track what kinds of messages trigger bootstrap Changes • src/hooks/internal-hooks.ts — Add optional incomingMessage to AgentBootstrapHookContext • src/agents/bootstrap-hooks.ts — Accept and forward incomingMessage • src/agents/bootstrap-files.ts — Thread through resolveBootstrapFilesForRun and resolveBootstrapContextForRun • src/agents/pi-embedded-runner/run/attempt.ts — Pass params.prompt as incomingMessage at the call site • Tests added for propagation and undefined handling Design decisions • Optional field (incomingMessage?: string) — fully backward compatible • Undefined when unavailable — compaction, heartbeats, CLI runs won't have a message • Only threaded through embedded runner — CLI and compact paths naturally pass undefined • No changes to hook registration API — existing hooks work unchanged Testing 3 new test cases: propagation through hooks, propagation through full pipeline, undefined when not provided. <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR extends the internal `agent:bootstrap` hook context to include an optional `incomingMessage?: string`, allowing bootstrap hooks to tailor injected bootstrap/context files based on the current user prompt. The value is threaded through the bootstrap resolution pipeline (`resolveBootstrapContextForRun` → `resolveBootstrapFilesForRun` → `applyBootstrapHookOverrides`) and is populated by the embedded runner (`runEmbeddedAttempt`) using `params.prompt`. Tests were added to verify propagation and the `undefined` case when not supplied. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk. - Changes are small, additive, and type-safe (optional field threaded through existing call chain). Tests cover both propagation and the undefined/default case. No behavioral changes occur unless a hook opts into the new field. - No files require special attention <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> **Context used:** - Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8)) - Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13)) <!-- /greptile_comment -->

Most Similar PRs