Repository navigation
feat: add the Claude Agent SDK coding agent #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
ef64e72
feat: replace the starter agent with the coding agent sample
zimeg 582d24c
test: disable tracing where tools are invoked so listener tests stay …
zimeg c2fc19a
feat: add the Claude Agent SDK coding agent
zimeg c51ec72
fix: read the OAuth state secret from SLACK_STATE_SECRET
zimeg 7e9a87a
Merge branch 'clack/coding-agent-openai-agents-sdk' into clack/coding…
zimeg 3802575
fix: read the claude-agent-sdk OAuth state secret from SLACK_STATE_SE…
zimeg 1b9dd34
fix: address review on secret prefixes, workflow permissions, and oau…
zimeg de4175d
Merge branch 'clack/coding-agent-openai-agents-sdk' into clack/coding…
zimeg 129b7d4
fix: match the openai-agents-sdk review changes in claude-agent-sdk
zimeg 35ddd6b
Merge branch 'main' into clack/coding-agent-claude-agent-sdk
zimeg e5e3005
fix: match the python sample's runtime and slack project config
zimeg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ jobs: | |
| strategy: | ||
| matrix: | ||
| directory: | ||
| - claude-agent-sdk | ||
| - openai-agents-sdk | ||
| defaults: | ||
| run: | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ jobs: | |
| strategy: | ||
| matrix: | ||
| directory: | ||
| - claude-agent-sdk | ||
| - openai-agents-sdk | ||
| defaults: | ||
| run: | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,5 +10,3 @@ | |
| # Slack CLI | ||
| */.slack/apps.json | ||
| */.slack/apps.dev.json | ||
| */.slack/cache/ | ||
| */.slack/config.json | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # Required, set your Anthropic API key. | ||
| ANTHROPIC_API_KEY=YOUR_ANTHROPIC_API_KEY | ||
|
|
||
| # Optional, uncomment and set when running without the Slack CLI (npm start). | ||
| # SLACK_APP_TOKEN=YOUR_SLACK_APP_TOKEN | ||
| # SLACK_BOT_TOKEN=YOUR_SLACK_BOT_TOKEN | ||
|
|
||
| # Optional, uncomment and set for OAuth mode (node app-oauth.js). | ||
| # SLACK_CLIENT_ID=YOUR_SLACK_CLIENT_ID | ||
| # SLACK_CLIENT_SECRET=YOUR_SLACK_CLIENT_SECRET | ||
| # SLACK_SIGNING_SECRET=YOUR_SLACK_SIGNING_SECRET | ||
| # SLACK_STATE_SECRET=YOUR_SLACK_STATE_SECRET | ||
|
|
||
| # Optional, uncomment and set when using a custom Slack instance. | ||
| # SLACK_API_URL=YOUR_SLACK_API_URL |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # Claude Code | ||
| .claude/*.local.json | ||
|
|
||
| # Environment | ||
| .env* | ||
| !.env.sample | ||
|
|
||
| # Logs | ||
| logs/ | ||
|
|
||
| # macOS | ||
| .DS_Store | ||
|
|
||
| # Node.js | ||
| node_modules/ | ||
|
|
||
| # OAuth | ||
| data/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| apps.dev.json | ||
| cache/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "manifest": { | ||
| "source": "local" | ||
| }, | ||
| "project_id": "452c1566-00e1-424d-bcca-3ee66ffe370b" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| { | ||
| "hooks": { | ||
| "get-hooks": "npx -q --no-install -p @slack/cli-hooks slack-cli-get-hooks" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # AGENTS.md | ||
|
|
||
| Guidance for coding agents working in this directory. Refer to the root `../AGENTS.md` for repository-wide structure and commands. | ||
|
|
||
| ## Claude Agent SDK specifics | ||
|
|
||
| **Agents (`agent/agent.js`)** are two sets of `query()` options with pinned models: a routing `requestAgent` (`claude-haiku-4-5`) whose only tool is `create_code_channel`, and the coding `agent` (`claude-sonnet-5-5`) with every other tool. Tools are `tool()` definitions with zod arguments, one per file under `agent/tools/`. Each file exports a function of the run's deps (`AgentDeps` or `RequestDeps`, both in `agent/sessions.js`) that returns the tool, since the SDK calls a tool with only its arguments. Each run serves its tools with `createSdkMcpServer()`, so the model sees each as `mcp__coding-agent__<name>`. Optional arguments are `.optional()`, and the model leaves them out. Both agents set `tools: []`, `settingSources: []`, and `strictMcpConfig: true`, so they get none of Claude Code's built-in tools and none of the settings, `CLAUDE.md` files, or MCP servers on the machine. `verbatimPrompts: true` keeps an `@path` in a Slack message from reading a local file. | ||
|
|
||
| **Runs** call the SDK's `query()` once per run from Bolt listeners, which runs the Claude Code CLI bundled with the SDK. Coding turns allow `MAX_TURNS` model calls, and a turn that uses them all (`error_max_turns`) ends with a message, keeping its history. A `PostToolUse` hook returns `continue: false` to end the run early once there's nothing left to do: after `create_code_channel` succeeds for the routing agent, and after `archive_channel` for the coding agent. A result with `is_error` throws, so the turn posts a warning. Every run also names its MCP server in `--mcp-config`: the SDK registers the server only once the CLI starts, and resuming a deferred call looks for its tool before that. | ||
|
|
||
| **Turns** go through `agent/turns.js`, which doesn't import the SDK. A turn that throws posts a warning and moves the session back to `active`, keeping the history from the last finished turn. Model-written replies use `markdown_text`, since the model writes standard markdown. | ||
|
|
||
| **Tool errors.** A tool that throws reaches the model as an error result with the error's message, which the SDK's MCP server does for every tool. A Slack API error a tool expects, a `WebAPIPlatformError`, is returned to the model as the tool's result. | ||
|
|
||
| **Stopping** sets `session.stopped`, and so does archiving the channel from Slack. The `PreToolUse` hook from `gateToolCalls` (`agent/guardrails.js`) then denies every tool call and tells the model to wrap up, and the turn posts nothing when it finishes. | ||
|
|
||
| **Conversation history** lives in the Claude Code session transcript. `session.history` is the list of each run's result message, and the next run resumes from the last one's `session_id`. | ||
|
|
||
| **Command approvals.** The `PreToolUse` hook wraps `commandNeedsApproval()` from `agent/approvals.js` and returns `defer` for a `run_command` that needs approval, which ends the run with `deferred_tool_use` on its result. A paused run is a `PausedRun` (its history, ending with that result), parked in `pendingStore` with the ts of its Approve/Deny message, so a click only resumes the run its buttons were posted for. `resumeRun` resumes the session with a prompt that sends nothing: the CLI asks the hook about the waiting call again, and the hook answers with the decision. A newer message in the channel retires a pending approval, so a late click can't resume an older run over it. The next run then finds the waiting call on the last result, and the hook hands it to `answerUnanswered`, the `canUseTool` callback, which denies it as not run and interrupts that old turn, so no model call is spent on it before the new message. | ||
|
|
||
| ## Testing | ||
|
|
||
| Tests use Node's test runner (`node --test`) and fake the Slack client with `fakeClient()` from `tests/helpers.js`, which mirrors the real client's methods. Listener tests stand in for the agent's runs with `t.mock.method(runs, 'startRun', ...)`, and `tests/agent/agent.test.js` stands in for the SDK with `t.mock.method(sdk, 'query', ...)`. `tests/invoke.js` calls a tool through its MCP server, the way a run does. `tests/agent/runs.test.js` runs the real agents and the bundled CLI against `tests/fake-model.js`, a local stand-in for the Anthropic Messages API that returns scripted tool calls and replies, passed to each run through the `env` option, so the SDK seams are tested without calling Anthropic. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| MIT License | ||
|
|
||
| Copyright (c) 2026 Slack Technologies, LLC | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.