-
-
Notifications
You must be signed in to change notification settings - Fork 39.8k
Description
Summary
Implement the message:received and message:sent hooks listed as "Future Events" in the hooks documentation.
Motivation
The current hooks system supports command events (command:new, command:reset) and lifecycle events (agent:bootstrap, gateway:startup), but lacks per-message hooks. This limits automation possibilities:
- Per-message context injection - RAG systems, memory retrieval, user preference lookup
- Conversation logging - Analytics, audit trails, compliance
- Response post-processing - Filtering, transformation, caching
These events are already listed as planned in the docs under "Future Events".
Use Cases
1. Memory/RAG Integration
Inject relevant context before each LLM call, store exchanges after.
2. Usage Analytics
Track message patterns, response times, model usage per user/channel.
3. Content Filtering
Pre-filter user messages or post-filter agent responses.
4. Caching Layer
Cache common responses, serve from cache when appropriate.
Proposed API
message:received
Fires when a message is received, before agent processing.
interface MessageReceivedEvent extends HookEvent {
type: 'message';
action: 'received';
sessionKey: string;
timestamp: Date;
context: {
message: {
content: string;
senderId: string;
channelId: string;
messageId?: string;
};
session: {
sessionKey: string;
sessionId: string;
agentId: string;
};
// Hooks can set this to inject content
injection?: {
systemPrompt?: string;
userContext?: string;
};
};
}message:sent
Fires when agent sends a response, after generation.
interface MessageSentEvent extends HookEvent {
type: 'message';
action: 'sent';
sessionKey: string;
timestamp: Date;
context: {
request: {
content: string;
senderId: string;
channelId: string;
};
response: {
content: string;
model: string;
latencyMs: number;
};
session: {
sessionKey: string;
sessionId: string;
agentId: string;
};
};
}Example Hook
// hooks/my-hook/handler.ts
import type { HookHandler } from 'clawdbot/hooks';
const handler: HookHandler = async (event) => {
if (event.type === 'message' && event.action === 'received') {
// Example: inject context before LLM call
const context = await fetchRelevantContext(event.context.message.content);
if (context) {
event.context.injection = {
systemPrompt: \`## Context\n\${context}\n---\n\`
};
}
}
if (event.type === 'message' && event.action === 'sent') {
// Example: log the exchange
await logExchange(
event.context.request.content,
event.context.response.content
);
}
};
export default handler;Implementation Notes
Trigger Points
message:received: After message parsing, before system prompt construction.
message:sent: After LLM response, before channel delivery.
Injection Mechanism
Hooks set context.injection.systemPrompt or context.injection.userContext. The prompt builder prepends these to the respective prompt sections.
Performance
- Async execution with configurable timeout (suggest 5s default)
- Parallel execution of multiple hooks
- Graceful degradation on hook failure
Files to Modify
| File | Changes |
|---|---|
src/hooks/types.ts |
Add event types |
src/auto-reply/reply/agent-loop.ts |
Add trigger points |
src/auto-reply/reply/prompt-builder.ts |
Apply injections |
docs/hooks.md |
Document new events |
Backwards Compatibility
- New events only, no breaking changes
- Injection is opt-in
- Existing hooks unaffected
This implements the events already listed under "Future Events" in the hooks documentation.