Skip to content

Commit 88c9cc8

Browse files
zzstoatzzclaude
andcommitted
feat: integrate learning-sdk into slackbot for persistent memory
- add letta_api_key_secret_name setting and load LETTA_API_KEY env var - wrap agent run with learning() context for per-user memory - add agentic-learning dependency each slack user gets their own memory agent (slackbot-{user_id}) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2134a30 commit 88c9cc8

3 files changed

Lines changed: 19 additions & 5 deletions

File tree

examples/slackbot/pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ dependencies = [
4242
"raggy[tpuf] @ git+https://github.com/zzstoatzz/raggy.git",
4343
"pretty-mod",
4444
"claude-agent-sdk",
45+
"agentic-learning",
4546
]
4647

4748

examples/slackbot/src/slackbot/api.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from contextlib import asynccontextmanager
66
from typing import Any
77

8+
from agentic_learning import learning
89
from fastapi import FastAPI, HTTPException, Request
910
from prefect import Flow, State, flow, get_run_logger, task
1011
from prefect.blocks.notifications import SlackWebhook
@@ -100,11 +101,13 @@ async def run_agent(
100101
settings=decorator_settings,
101102
max_tool_calls=settings.max_tool_calls_per_turn,
102103
):
103-
result = await create_agent(model=settings.model_name).run(
104-
user_prompt=cleaned_message,
105-
message_history=conversation,
106-
deps=user_context,
107-
)
104+
# wrap agent run with learning context for persistent memory
105+
with learning(agent=f"slackbot-{user_context['user_id']}"):
106+
result = await create_agent(model=settings.model_name).run(
107+
user_prompt=cleaned_message,
108+
message_history=conversation,
109+
deps=user_context,
110+
)
108111
finally:
109112
_progress_message.reset(token)
110113
_tool_usage_counts.reset(counts_token)

examples/slackbot/src/slackbot/settings.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ def validate_log_level(cls, v: str) -> str:
5656
default="anthropic-api-key",
5757
description="Name of the Prefect secret block containing Anthropic API key",
5858
)
59+
letta_api_key_secret_name: str = Field(
60+
default="letta-api-key",
61+
description="Name of the Prefect secret block containing Letta API key",
62+
)
5963

6064
vector_store_type: Literal["turbopuffer"] = Field(
6165
default="turbopuffer", description="Type of vector store to use"
@@ -94,6 +98,12 @@ def _apply_post_validation_defaults(self) -> "SlackbotSettings":
9498
os.environ["TURBOPUFFER_API_KEY"] = api_key
9599
except Exception:
96100
pass # If secret doesn't exist, turbopuffer will handle the error
101+
if not os.getenv("LETTA_API_KEY"):
102+
try:
103+
api_key = Secret.load(self.letta_api_key_secret_name, _sync=True).get() # type: ignore
104+
os.environ["LETTA_API_KEY"] = api_key
105+
except Exception:
106+
pass # If secret doesn't exist, learning-sdk won't be used
97107
if not self.admin_slack_user_id:
98108
self.admin_slack_user_id = Variable.get("admin-slack-id", _sync=True)
99109
return self

0 commit comments

Comments
 (0)