diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md deleted file mode 100644 index df589c5..0000000 --- a/.claude/CLAUDE.md +++ /dev/null @@ -1,75 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## What This Is - -A monorepo containing three parallel implementations of a **Starter Agent** for Slack built with Bolt for Python. All implementations are functionally identical from the Slack user's perspective but use different AI agent frameworks: - -- `claude-agent-sdk/` -- Built with **Claude Agent SDK** -- `openai-agents-sdk/` -- Built with **OpenAI Agents SDK** -- `pydantic-ai/` -- Built with **Pydantic AI** - -This is a minimal starter template. It includes one example tool (emoji reactions) and optional Slack MCP Server integration. - -## Commands - -All commands must be run from within the respective project directory (`claude-agent-sdk/`, `openai-agents-sdk/`, or `pydantic-ai/`). - -```sh -# Run the app (requires .env with OPENAI_API_KEY or ANTHROPIC_API_KEY; Slack tokens optional with CLI) -slack run # via Slack CLI -python3 app.py # directly - -# Lint and format (CI runs these on push to main and all PRs) -ruff check . -ruff format --check . - -# Run tests -pytest -``` - -## Monorepo Structure - -``` -.github/ # Shared CI workflows and dependabot config -claude-agent-sdk/ # Claude Agent SDK implementation -openai-agents-sdk/ # OpenAI Agents SDK implementation -pydantic-ai/ # Pydantic AI implementation -``` - -CI runs ruff lint/format checks against all directories via a matrix strategy in `.github/workflows/ruff.yml`. Dependabot monitors `pyproject.toml` in all directories independently. - -## Architecture (shared across all implementations) - -Three-layer design: **app.py** -> **listeners/** -> **agent/** - -**Entry point (`app.py`)** initializes Bolt with Socket Mode and calls `register_listeners(app)`. - -**Listeners** are organized by Slack platform feature: -- `listeners/events/` -- `app_home_opened`, `app_mentioned`, `message` -- `listeners/actions/` -- `feedback_buttons` - -Each sub-package has a `register(app)` function called from `listeners/__init__.py`. - -**AgentDeps** (`agent/deps.py`) is a dataclass carrying `client`, `user_id`, `channel_id`, `thread_ts`. Constructed in each listener handler and passed to the agent at runtime. - -**Conversation history** (`thread_context/store.py`) is a thread-safe in-memory dict keyed by `(channel_id, thread_ts)` with TTL-based cleanup. This enables multi-turn context. - -**Handler flow** (DM, mention): get history from store -> run agent -> post response in thread with feedback blocks -> store updated messages. - -## Key Differences Between Implementations - -| Aspect | Claude Agent SDK | OpenAI Agents SDK | Pydantic AI | -|--------|-----------------|-------------------|-------------| -| Agent file | `agent/agent.py` | `agent/agent.py` | `agent/agent.py` | -| App type | `AsyncApp` (fully async) | `App` (sync) | `App` (sync) | -| Agent definition | `ClaudeSDKClient` with `ClaudeAgentOptions` | `Agent[AgentDeps](model="gpt-4.1-mini")` | `Agent(deps_type=AgentDeps)` | -| Model config | Managed by SDK (Claude models) | Set directly on agent constructor | `get_model()` selects provider at runtime (Anthropic preferred) | -| Tool definition | `@tool` decorated functions via MCP server | `@function_tool` decorated functions | Plain async functions | -| Tool context param | `args` dict (no context param) | `RunContextWrapper[AgentDeps]` | `RunContext[AgentDeps]` | -| Execution | `await run_agent(text, session_id=...)` | `Runner.run_sync(agent, input=..., context=...)` | `agent.run_sync(text, model=..., deps=..., message_history=...)` | -| Result output | `response_text` from collected `TextBlock.text` | `result.final_output` | `result.output` | -| Conversation history | Session-based via `resume` (server-side) | `list` stored locally | `list[ModelMessage]` stored locally | -| API key env var | `ANTHROPIC_API_KEY` | `OPENAI_API_KEY` | `ANTHROPIC_API_KEY` or `OPENAI_API_KEY` | -| Feedback blocks | Native `FeedbackButtonsElement` | Native `FeedbackButtonsElement` | Native `FeedbackButtonsElement` | diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..b1e6ef2 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,17 @@ +# AGENTS.md + +This file provides guidance to coding agents when working with code in this repository. + +## What This Is + +A monorepo with three functionally identical implementations of the Starter Agent for Slack built with Bolt for Python, each self-contained with its own `AGENTS.md`: + +- `claude-agent-sdk/`: Claude Agent SDK +- `openai-agents-sdk/`: OpenAI Agents SDK +- `pydantic-ai/`: Pydantic AI + +Work and run commands inside one of them. Keep the three in parity: a user-facing change to one usually belongs in the others. + +## Slack Plugin + +To install the Slack plugin for your coding agent, follow [Claude Code, Codex, Cursor, and Other Coding Agents](./README.md#claude-code-codex-cursor-and-other-coding-agents) in the README. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/claude-agent-sdk/.claude/CLAUDE.md b/claude-agent-sdk/.claude/CLAUDE.md deleted file mode 100644 index 1a1c6c7..0000000 --- a/claude-agent-sdk/.claude/CLAUDE.md +++ /dev/null @@ -1,19 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -See the root `../.claude/CLAUDE.md` for monorepo-wide architecture, commands, and a comparison of all implementations. - -## Claude Agent SDK Specifics - -**App (`app.py`)** uses `AsyncApp` from Bolt for Python. All listeners and Slack API calls are fully async (`await`). - -**Agent (`agent/agent.py`)** uses `ClaudeSDKClient` from the Claude Agent SDK. Tools are registered via `create_sdk_mcp_server()` and passed as `mcp_servers` in `ClaudeAgentOptions`. The `run_agent()` function is async and returns `(response_text, session_id)`. - -**Tools (`agent/tools/`)** are defined with the `@tool` decorator from `claude_agent_sdk`. One example tool (emoji reaction) is included. Tools are registered into a single MCP server via `create_sdk_mcp_server()`. - -**Conversation history** is managed server-side by the Claude Agent SDK via sessions. The local `SessionStore` (`thread_context/store.py`) only maps `(channel_id, thread_ts)` to session IDs. Sessions are resumed via `ClaudeAgentOptions(resume=session_id)`. - -**Feedback blocks** use the native `FeedbackButtonsElement` from `slack_sdk.models.blocks`. A single `feedback` action ID is registered. - -**Dependencies** (`agent/deps.py`) use `AsyncWebClient` from `slack_sdk.web.async_client` instead of the sync `WebClient`. diff --git a/claude-agent-sdk/AGENTS.md b/claude-agent-sdk/AGENTS.md new file mode 100644 index 0000000..345fc1f --- /dev/null +++ b/claude-agent-sdk/AGENTS.md @@ -0,0 +1,20 @@ +# AGENTS.md + +This file provides guidance to coding agents when working with code in this repository. + +## What This Is + +A **Starter Agent** for Slack built with Bolt for Python and the **Claude Agent SDK**. This is a minimal starter template. It includes one example tool (emoji reactions) and optional Slack MCP Server integration. + +## Slack Plugin + +To install the Slack plugin for your coding agent, follow [Claude Code, Codex, Cursor, and Other Coding Agents](./README.md#claude-code-codex-cursor-and-other-coding-agents) in the README. + +## Before you finish + +Run `ruff check .`, `ruff format --check .`, and `pytest`. CI runs the same on every PR. + +## Code Style + +- Snake-case filenames +- No code comments. Make the code explain itself with clear names, tests, or types. Put the reason for a change in the PR description. diff --git a/claude-agent-sdk/CLAUDE.md b/claude-agent-sdk/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/claude-agent-sdk/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/openai-agents-sdk/.claude/CLAUDE.md b/openai-agents-sdk/.claude/CLAUDE.md deleted file mode 100644 index 51e39ca..0000000 --- a/openai-agents-sdk/.claude/CLAUDE.md +++ /dev/null @@ -1,13 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -See the root `../.claude/CLAUDE.md` for monorepo-wide architecture, commands, and a comparison of all implementations. - -## OpenAI Agents SDK Specifics - -**Agent (`agent/agent.py`)** is an `Agent[AgentDeps]` with the model set directly on the agent (`model="gpt-4.1-mini"`). Tools are `@function_tool`-decorated async functions, each in its own file under `agent/tools/`. Execution uses `Runner.run_sync(agent, input=..., context=deps)`. - -**Conversation history** is stored as a generic `list` and must be manually combined with new user input before passing to `Runner.run_sync()`: `input_items = history + [{"role": "user", "content": text}]`. After execution, `result.to_input_list()` is stored back. - -**Feedback blocks** use the native `FeedbackButtonsElement` from `slack_sdk.models.blocks`. A single `feedback` action ID is registered. \ No newline at end of file diff --git a/openai-agents-sdk/AGENTS.md b/openai-agents-sdk/AGENTS.md new file mode 100644 index 0000000..2a46a05 --- /dev/null +++ b/openai-agents-sdk/AGENTS.md @@ -0,0 +1,20 @@ +# AGENTS.md + +This file provides guidance to coding agents when working with code in this repository. + +## What This Is + +A **Starter Agent** for Slack built with Bolt for Python and the **OpenAI Agents SDK**. This is a minimal starter template. It includes one example tool (emoji reactions) and optional Slack MCP Server integration. + +## Slack Plugin + +To install the Slack plugin for your coding agent, follow [Claude Code, Codex, Cursor, and Other Coding Agents](./README.md#claude-code-codex-cursor-and-other-coding-agents) in the README. + +## Before you finish + +Run `ruff check .`, `ruff format --check .`, and `pytest`. CI runs the same on every PR. + +## Code Style + +- Snake-case filenames +- No code comments. Make the code explain itself with clear names, tests, or types. Put the reason for a change in the PR description. diff --git a/openai-agents-sdk/CLAUDE.md b/openai-agents-sdk/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/openai-agents-sdk/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/pydantic-ai/.claude/CLAUDE.md b/pydantic-ai/.claude/CLAUDE.md deleted file mode 100644 index 19eea19..0000000 --- a/pydantic-ai/.claude/CLAUDE.md +++ /dev/null @@ -1,13 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -See the root `../.claude/CLAUDE.md` for monorepo-wide architecture, commands, and a comparison of all implementations. - -## Pydantic AI Specifics - -**Agent (`agent/agent.py`)** is a Pydantic AI `Agent` with `deps_type=AgentDeps`. The model is **not** set on the agent (to avoid import-time client creation); instead `get_model()` selects the provider at runtime based on available API keys (`ANTHROPIC_API_KEY` preferred over `OPENAI_API_KEY`) and 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/`. - -**Conversation history** stores `list[ModelMessage]` from Pydantic AI and is passed directly as `message_history=` to `run_sync()`. - -**Feedback blocks** use the native `FeedbackButtonsElement` from `slack_sdk.models.blocks`. A single `feedback` action ID is registered. \ No newline at end of file diff --git a/pydantic-ai/AGENTS.md b/pydantic-ai/AGENTS.md new file mode 100644 index 0000000..f095375 --- /dev/null +++ b/pydantic-ai/AGENTS.md @@ -0,0 +1,20 @@ +# AGENTS.md + +This file provides guidance to coding agents when working with code in this repository. + +## What This Is + +A **Starter Agent** for Slack built with Bolt for Python and **Pydantic AI**. This is a minimal starter template. It includes one example tool (emoji reactions) and optional Slack MCP Server integration. + +## Slack Plugin + +To install the Slack plugin for your coding agent, follow [Claude Code, Codex, Cursor, and Other Coding Agents](./README.md#claude-code-codex-cursor-and-other-coding-agents) in the README. + +## Before you finish + +Run `ruff check .`, `ruff format --check .`, and `pytest`. CI runs the same on every PR. + +## Code Style + +- Snake-case filenames +- No code comments. Make the code explain itself with clear names, tests, or types. Put the reason for a change in the PR description. diff --git a/pydantic-ai/CLAUDE.md b/pydantic-ai/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/pydantic-ai/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md