Skip to content

Commit ca607ff

Browse files
committed
chore: add .claude/CLAUDE.md
1 parent a8404d3 commit ca607ff

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

.claude/CLAUDE.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## What This Is
6+
7+
Casey is an AI-powered IT helpdesk agent for Slack, built with Bolt for Python and Pydantic AI. It uses simulated tools (knowledge base, ticket creation, password reset, system status, permissions lookup) to demonstrate an agentic IT support workflow. All tool data is hardcoded for demo purposes.
8+
9+
## Commands
10+
11+
```sh
12+
# Run the app (requires .env with OPENAI_API_KEY; Slack tokens optional with CLI)
13+
slack run # via Slack CLI
14+
python3 app.py # directly
15+
16+
# Lint and format (CI runs these on push to main and all PRs)
17+
ruff check .
18+
ruff format --check .
19+
20+
# Run tests
21+
pytest
22+
```
23+
24+
## Architecture
25+
26+
Three-layer design: **app.py****listeners/****agent/**
27+
28+
**Entry point (`app.py`)** initializes Bolt with Socket Mode and calls `register_listeners(app)`.
29+
30+
**Listeners** are organized by Slack platform feature:
31+
- `listeners/events/``app_home_opened`, `app_mentioned`, `message_im`
32+
- `listeners/actions/``category_buttons` (regex `^category_`), `feedback_good`, `feedback_bad`
33+
- `listeners/views/``issue_submission` modal handler
34+
35+
Each sub-package has a `register(app)` function called from `listeners/__init__.py`.
36+
37+
**Agent (`agent/casey.py`)** is a Pydantic AI `Agent` with `deps_type=CaseyDeps`. The model is **not** set on the agent (to avoid import-time OpenAI client creation); instead `DEFAULT_MODEL` (`openai:gpt-4o-mini`) is passed at each `run_sync()` call site. Tools are passed via the `tools=[]` constructor parameter (not decorators) so each tool lives in its own file under `agent/tools/`.
38+
39+
**CaseyDeps** (`agent/deps.py`) is a dataclass carrying `client`, `user_id`, `channel_id`, `thread_ts`. It's constructed in each listener handler and passed as `deps=` to `run_sync()`.
40+
41+
**Conversation history** (`conversation/store.py`) is an in-memory dict keyed by `(channel_id, thread_ts)` storing `list[ModelMessage]` from Pydantic AI. This is what enables multi-turn context. The singleton `conversation_store` is imported from `conversation/`.
42+
43+
## Key Patterns
44+
45+
- All three message handlers (DM, mention, modal submit) follow the same flow: add :eyes: reaction → get history from store → `casey_agent.run_sync(text, model=DEFAULT_MODEL, deps=deps, message_history=history)` → post `result.output` in thread with feedback blocks → store `result.all_messages()`.
46+
- Emoji/reaction logic is in the handlers, not the agent. Resolution detection checks `result.output` against a hardcoded phrase list.
47+
- View builders (`app_home_builder.py`, `modal_builder.py`, `feedback_block.py`) return raw dicts or Block Kit objects, not views themselves. The handlers call `client.views_publish()` or `client.views_open()`.
48+
- The `message_im` handler filters out bot messages (`event.bot_id`) and subtypes to avoid self-reply loops.

0 commit comments

Comments
 (0)