Skip to content

Commit c748a19

Browse files
zimegClaude
andcommitted
feat: add the Claude Agent SDK coding agent
Adds claude-agent-sdk/, the coding agent built with the Claude Agent SDK. It shares structure, listeners, and the framework-free agent files with openai-agents-sdk/. Command approvals defer run_command from a PreToolUse hook and resume the Claude Code session with the decision. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
1 parent 2e86b5d commit c748a19

73 files changed

Lines changed: 4983 additions & 6 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/dependabot.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ updates:
33
- package-ecosystem: "pip"
44
directories:
55
- "/"
6+
- "/claude-agent-sdk"
67
- "/openai-agents-sdk"
78
schedule:
89
interval: "daily"

‎.github/workflows/ruff.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ jobs:
1515
strategy:
1616
matrix:
1717
directory:
18+
- claude-agent-sdk
1819
- openai-agents-sdk
1920
defaults:
2021
run:

‎.github/workflows/tests.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ jobs:
1515
strategy:
1616
matrix:
1717
directory:
18+
- claude-agent-sdk
1819
- openai-agents-sdk
1920
defaults:
2021
run:

‎AGENTS.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Guidance for coding agents working in this repository.
66

77
A monorepo for a **Coding Agent** sample for Slack, built with Bolt for Python. Each framework lives in its own directory as a standalone sample:
88

9+
- `claude-agent-sdk/` — built with the **Claude Agent SDK**
910
- `openai-agents-sdk/` — built with the **OpenAI Agents SDK**
1011

1112
Implementations share a structure and user experience, not code. Keep each one obvious on its own, written in its framework's idiom, rather than adding shared helpers.
@@ -31,6 +32,7 @@ pytest
3132

3233
```
3334
.github/ # Shared CI workflows and dependabot config
35+
claude-agent-sdk/ # Claude Agent SDK implementation
3436
openai-agents-sdk/ # OpenAI Agents SDK implementation
3537
```
3638

@@ -51,8 +53,8 @@ The flow: a mention or direct message outside a code channel runs a small routin
5153
Implementations share structure, not code, so these parts are kept the same by copying them and changing them everywhere at once:
5254

5355
- **The seam between `listeners/` and `agent/`.** Listeners import only from the `agent` package, never from the agent framework, so `listeners/` is the same in every implementation. `agent/__init__.py` provides `answer_request`, `find_session`, `run_turn`, `resume_turn`, `stop_turn`, and `end_session`.
54-
- **Framework-free files.** `agent/turns.py`, `agent/context.py`, `agent/approvals.py`, `agent/sessions.py`, `agent/workspace.py`, `agent/outcome.py`, and `agent/prompts.py` don't import the agent framework. The framework lives in `agent/agent.py`, `agent/guardrails.py`, and `agent/tools/`. `turns.py` calls only `run_request(prompt, deps)`, which returns the reply text, and `start_run(history, text, deps)` and `resume_run(paused, approved, deps)`, which return the `RunOutcome` in `agent/outcome.py`. The paused run is a handle `turns.py` passes back without looking inside, so each framework's way of pausing fits behind it.
55-
- **What the framework side keeps true.** `turns.py` relies on these, so every implementation keeps them: `create_code_channel` sets `deps.code_channel_id`, and `archive_channel` sets `session.archived`. Every code channel tool skips its call once `session.stopped` is set. A paused run's history already records the pending command as not run, so `turns.py` can drop a paused run without resuming it. Beyond that, `turns.py` only checks whether `history` is empty, to know a turn is the first.
56+
- **Framework-free files.** `agent/turns.py`, `agent/context.py`, `agent/approvals.py`, `agent/sessions.py`, `agent/workspace.py`, `agent/outcome.py`, and `agent/prompts.py` don't import the agent framework. The framework lives in `agent/agent.py`, `agent/guardrails.py`, and `agent/tools/`, and the Claude Agent SDK adds `agent/runtime.py` for the deps its tools can't be passed. `turns.py` calls only `run_request(prompt, deps)`, which returns the reply text, and `start_run(history, text, deps)` and `resume_run(paused, approved, deps)`, which return the `RunOutcome` in `agent/outcome.py`. The paused run is a handle `turns.py` passes back without looking inside, so each framework's way of pausing fits behind it.
57+
- **What the framework side keeps true.** `turns.py` relies on these, so every implementation keeps them: `create_code_channel` sets `deps.code_channel_id`, and `archive_channel` sets `session.archived`. Every code channel tool skips its call once `session.stopped` is set. `turns.py` can drop a paused run without resuming it, since the session's history then shows its pending command as not run: the history already records it that way, or the next run answers it that way before anything else. Beyond that, `turns.py` only checks whether `history` is empty, to know a turn is the first.
5658
- **Prompts.** `agent/prompts.py` is the same word for word in every implementation.
5759
- **Tools.** Every implementation offers the same tools with the same names, arguments, and descriptions, written with its framework's tool decorator. File tools stay inside the clone and can't write into `.git`.
5860
- **Command approvals.** `command_needs_approval(command)` is plain Python and the same in every implementation, wrapped in the framework's own approval hook. Read-only commands and local git changes run without asking. Anything that runs the repository's code or reaches outside the clone asks first. Commands run without a shell, so the check and the run split a command the same way. On Windows, `.cmd` and `.bat` programs like `npm` are the exception, since Windows runs them through `cmd.exe`.

‎README.md‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ A sample Slack agent that showcases [Slack Code](https://docs.slack.dev/ai/slack
77
88
## Choose your framework
99

10-
| App | Directory | Get started | Framework |
11-
| --------------------- | -------------------- | -------------------------------------------- | --------------------------------------------------------------- |
12-
| **OpenAI Agents SDK** | `openai-agents-sdk/` | [View README](./openai-agents-sdk/README.md) | [openai-agents](https://openai.github.io/openai-agents-python/) |
10+
| App | Directory | Get started | Framework |
11+
| --------------------- | -------------------- | -------------------------------------------- | -------------------------------------------------------------------------- |
12+
| **Claude Agent SDK** | `claude-agent-sdk/` | [View README](./claude-agent-sdk/README.md) | [claude-agent-sdk](https://platform.claude.com/docs/en/agent-sdk/overview) |
13+
| **OpenAI Agents SDK** | `openai-agents-sdk/` | [View README](./openai-agents-sdk/README.md) | [openai-agents](https://openai.github.io/openai-agents-python/) |
1314

1415
## What it can do
1516

‎claude-agent-sdk/.env.sample‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Required, set your Anthropic API key.
2+
ANTHROPIC_API_KEY=YOUR_ANTHROPIC_API_KEY
3+
4+
# Optional, uncomment and set when running without the Slack CLI (python3 app.py).
5+
# SLACK_APP_TOKEN=YOUR_SLACK_APP_TOKEN
6+
# SLACK_BOT_TOKEN=YOUR_SLACK_BOT_TOKEN
7+
8+
# Required for OAuth (app_oauth.py). Set your app's OAuth credentials.
9+
# SLACK_CLIENT_ID=YOUR_SLACK_CLIENT_ID
10+
# SLACK_CLIENT_SECRET=YOUR_SLACK_CLIENT_SECRET
11+
# SLACK_SIGNING_SECRET=YOUR_SLACK_SIGNING_SECRET
12+
13+
# Optional, uncomment and set when using a custom Slack instance.
14+
# SLACK_API_URL=YOUR_SLACK_API_URL

‎claude-agent-sdk/.gitignore‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Build
2+
build/
3+
dist/
4+
docs/_sources/
5+
docs/.doctrees
6+
7+
# Claude Code
8+
.claude/*.local.json
9+
10+
# Coverage
11+
.coverage
12+
cov_*
13+
coverage.xml
14+
15+
# Editors
16+
.idea/
17+
18+
# Environment
19+
.env*
20+
!.env.sample
21+
env*/
22+
venv/
23+
.venv*
24+
25+
# Logs
26+
logs/
27+
28+
# macOS
29+
.DS_Store
30+
31+
# OAuth
32+
data/
33+
34+
# Python
35+
__pycache__/
36+
*.db
37+
*.egg
38+
*.egg-info/
39+
*.eggs/
40+
*.py[cod]
41+
*.so
42+
.mypy_cache/
43+
.pytype/
44+
.python-version
45+
*~
46+
pip
47+
48+
# Testing
49+
.cache
50+
.pytest_cache/
51+
.tox
52+
tmp.txt

‎claude-agent-sdk/.slack/.gitignore‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
apps.dev.json
2+
cache/
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"manifest": {
3+
"source": "local"
4+
},
5+
"project_id": "e609f4b0-5cdd-4023-8d3a-a5bd0de0f817"
6+
}

‎claude-agent-sdk/.slack/hooks.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"hooks": {
3+
"get-hooks": "python3 -m slack_cli_hooks.hooks.get_hooks"
4+
}
5+
}

0 commit comments

Comments
 (0)