laser_sdk/agent/memory_handler.rs
1use crate::agent::consumer::{AgentHandler, AgentMessage};
2use crate::agent::ctx::AgentCtx;
3use crate::error::LaserError;
4use crate::memory::{MemoryHandle, MemoryKind};
5
6/// Wraps an [`AgentHandler`] so the runtime turns each handled message into
7/// queryable memory: after the inner handler succeeds, the message is remembered
8/// under its conversation. This is the runtime half of agent memory. Recall is
9/// the other half, and a handler reads it directly from
10/// [`AgentCtx::laser`](crate::agent::AgentCtx::laser):
11/// `ctx.laser().memory("agent-mem").recall(conversation).fetch().await`.
12///
13/// A memory write that fails does not fail the turn (the message was already
14/// handled, and re-running it would repeat the handler's effects), so a failed
15/// remember is dropped rather than retried.
16pub struct MemoryHandler<H> {
17 inner: H,
18 memory: MemoryHandle,
19 remember_kind: Option<MemoryKind>,
20}
21
22impl<H> MemoryHandler<H> {
23 /// Wrap `inner`, writing to `memory`. Remembering is off until
24 /// [`auto_remember`](Self::auto_remember) selects a kind.
25 pub fn new(inner: H, memory: MemoryHandle) -> Self {
26 Self {
27 inner,
28 memory,
29 remember_kind: None,
30 }
31 }
32
33 /// Remember each successfully handled message under its conversation, stored
34 /// as `kind` (`MemoryKind::Message` for a chat turn).
35 #[must_use]
36 pub fn auto_remember(mut self, kind: MemoryKind) -> Self {
37 self.remember_kind = Some(kind);
38 self
39 }
40}
41
42impl<H: AgentHandler + Sync> AgentHandler for MemoryHandler<H> {
43 async fn handle(&self, message: &AgentMessage, ctx: &AgentCtx<'_>) -> Result<(), LaserError> {
44 self.inner.handle(message, ctx).await?;
45 if let Some(kind) = self.remember_kind {
46 let mut remember = self
47 .memory
48 .remember(message.payload.clone())
49 .scope(message.provenance.conversation_id)
50 .kind(kind);
51 if let Some(agent) = &message.provenance.agent {
52 remember = remember.agent(agent.clone());
53 }
54 // A handled turn is durable regardless of whether its memory copy
55 // lands, so a write failure is dropped, never retried.
56 let _ = remember.send().await;
57 }
58 Ok(())
59 }
60}