diff --git a/README.md b/README.md index c80a34c..10c10d9 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,30 @@ # Coding Agent for Slack -A sample Slack agent that showcases [Slack Code](https://docs.slack.dev/ai/slack-code/) built with [Bolt for JavaScript](https://docs.slack.dev/tools/bolt-js/). Mention it in a channel with a task and a repo, and it decides whether to answer in place or create a dedicated **code channel** for the work. In a code channel it clones the repo into a temp workspace, makes changes with your approval, and keeps the channel's plan, context bar, and code tab current as it goes. +A sample Slack agent that showcases [Slack Code](https://docs.slack.dev/ai/slack-code/) built with [Bolt for JavaScript](https://docs.slack.dev/tools/bolt-js/). Mention it in a channel with a task and a project repo, and it decides whether to answer in place or create a dedicated **code channel** for the work. In a code channel it clones the repo into a temporary workspace and makes changes with the necessary approvals, keeping the channel's plan, context bar, and code tab current as it goes. > [!WARNING] -> **This agent runs commands generated by a language model on the machine running the app.** Only run it against trusted, throwaway repositories, on a machine you're comfortable letting it operate. Refer to the framework README for how command approvals work. +> **This agent runs commands generated by a language model on the machine running the app.** Only run it against trusted repositories on a machine you're comfortable letting it operate. Refer to the framework README for how command approvals work. -## Choose your framework +## Choose Your Framework -| App | Directory | Get started | Framework | -| --------------------- | -------------------- | -------------------------------------------- | -------------------------------------------------------------------------- | -| **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) | -| **OpenAI Agents SDK** | `openai-agents-sdk/` | [View README](./openai-agents-sdk/README.md) | [openai-agents](https://openai.github.io/openai-agents-js/) | +This repo contains the same app built with two different AI agent frameworks. Pick the one that fits your stack: -## What it can do +| App | Directory | Get Started | Framework | +|-----|-----------|-------------|-----------| +| **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) | +| **OpenAI Agents SDK** | `openai-agents-sdk/` | [View README](./openai-agents-sdk/README.md) | [openai-agents](https://openai.github.io/openai-agents-js/) | + +All implementations share the same Slack listener layer and the same user experience. The only difference is how the agent is defined and executed under the hood. + +## What It Can Do + +The coding agent interacts with users through four entry points: -- **Channel @mentions and direct messages** — Mention the agent with a task, or message it directly. Quick questions get an answer in place; work that takes more than one message gets a code channel linked back to your message, along with the conversation it came from. -- **Code channels** — Keep chatting in the channel without an @mention. The agent writes its plan to a Plan tab you can comment on, publishes its changes to the code tab, and pins the repo, branch, and CI status to the context bar. -- **Command approvals** — File edits, read-only commands, and local git changes run right away. Anything else, like running tests, posts Approve and Deny buttons and waits for your decision. -- **Slash commands** — The agent registers commands like `/run-tests` for each channel and decides what each one does. -- **Wrap up** — When you say the work is done, the agent posts a summary back to your original message and archives the channel. - **App Home** — The Home tab explains how to start a task. +- **Direct Messages** — Message the agent directly. Quick questions get an answer in place; work that takes more than one message gets a code channel linked back to your message. +- **Channel @mentions** — Mention the agent in any channel with a task and a repo. It answers in place, or creates a code channel for the work along with the conversation it came from. +- **Code Channels** — Keep chatting in the channel without an @mention. The agent writes its plan to a Plan tab you can comment on, publishes its changes to the code tab, and pins the repo, branch, and CI status to the context bar. + +In a code channel, file edits, read-only commands, and local git changes run right away. Anything else posts Approve and Deny buttons, and runs only if someone in the channel approves it. The agent also registers slash commands like `/run-tests` for each channel and decides what each one does. When you say the work is done, it posts a summary back to your original message and archives the channel. For full setup instructions, pick a framework above and follow the README in that directory. diff --git a/claude-agent-sdk/README.md b/claude-agent-sdk/README.md index c836a27..38d92fe 100644 --- a/claude-agent-sdk/README.md +++ b/claude-agent-sdk/README.md @@ -1,9 +1,9 @@ # Coding Agent for Slack (Bolt for JavaScript and Claude Agent SDK) -A sample Slack **coding agent** built with [Bolt for JavaScript](https://docs.slack.dev/tools/bolt-js/) and the [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview) using models from [Anthropic](https://www.anthropic.com). When you mention the agent, it decides whether to reply in place or create a dedicated **code channel** for the work. In a code channel it clones a repository into a temp workspace, does real work there, and keeps the channel's plan, context bar, and code tab current as it goes. +A sample Slack agent that showcases [Slack Code](https://docs.slack.dev/ai/slack-code/) built with [Bolt for JavaScript](https://docs.slack.dev/tools/bolt-js/) and the [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview) using models from [Anthropic](https://www.anthropic.com). Mention it in a channel with a task and a project repo, and it decides whether to answer in place or create a dedicated **code channel** for the work. In a code channel it clones the repo into a temporary workspace and makes changes with the necessary approvals, keeping the channel's plan, context bar, and code tab current as it goes. > [!WARNING] -> **This agent runs commands generated by a language model on the machine running the app.** Only read-only commands and local git changes run without asking. Everything else, including the repo's own tests and builds, needs approval in Slack before it runs (see [Command approvals](#command-approvals)), and anyone in the code channel can approve. Approval is the safety gate, so read each command before you approve it. Commands run without the app's tokens or anything that looks like a credential in their environment. **Only run this sample against trusted, throwaway repositories, and on a machine you're comfortable letting it operate.** It is a reference sample, not a hardened product. +> **This agent runs commands generated by a language model on the machine running the app.** Only run it against trusted repositories on a machine you're comfortable letting it operate. Refer to [Command approvals](#command-approvals) for how command approvals work. ## App Overview @@ -12,7 +12,7 @@ The coding agent works like this: 1. You `@Coding Agent fix the flaky login test in ` in any channel, or send the agent a direct message. 2. The agent decides how to handle it, reading the thread or direct message the request came from. A question gets an answer in place. Work that takes more than one message gets a code channel, created with the `create_code_channel` tool and linked back to your message. 3. Slack seeds the new channel with your request, mention included, and that mention starts the session there, along with the conversation the request came from. The agent clones the repo, pins it to the context bar, writes a plan, and registers a few slash commands for the channel. -4. It reads and edits files with `read_file`, `edit_file`, and `write_file`, which stay inside the clone and never ask. It runs commands with `run_command`: read-only commands (`ls`, `grep`, `git diff`, …) and local git changes (`git switch -c`, `git commit`, …) run immediately; anything else, including tests, asks for your approval first. +4. It reads and edits files and runs other commands in the clone. Riskier commands ask for your approval first. 5. It publishes the diff to the code tab and summarizes what it did. 6. Keep chatting in the channel (no `@`-mention needed), comment on the plan, or use its slash commands to iterate. Messages sent while the agent works go into its next turn together. 7. When you say it's done, the agent posts a summary, which is shared back to your original message, and archives the channel. @@ -38,8 +38,6 @@ Each code channel method is a tool the model calls when it decides to, in [`agen | `read_file`, `write_file`, `edit_file` | Local files in that directory | | `run_command` | A local program in that directory, run without a shell | -`create_code_channel` is the only tool when answering a mention outside a code channel, and the one tool missing inside it, so the agent can't create a channel from a channel. The session status belongs to the session lifecycle rather than the model, so the listeners call `agents.sessions.setStatus` around every turn (`processing` while working, `suspended` while waiting on an approval, `active` when done). Wrapping up is the exception: `archive_channel` sets `closed` itself, right before it archives the channel. - ### Code channel behavior - **Plan as a canvas.** The plan is attached with comment access, so people can comment but only the agent edits. `read_plan` gives the agent open comments each turn, and `setCanvasContent` keeps comments anchored to the sections it didn't change. @@ -56,9 +54,9 @@ Each code channel method is a tool the model calls when it decides to, in [`agen Every tool call the coding agent makes goes through a Claude Agent SDK `PreToolUse` hook ([`agent/guardrails.js`](./agent/guardrails.js)), and for `run_command` it asks `commandNeedsApproval` in [`agent/approvals.js`](./agent/approvals.js): -- **Read-only** commands like `ls`, `grep`, and `git diff`, and **local git changes** like `git add`, `git commit`, and `git switch -c`, run with no prompt. A path outside the clone, like `/etc`, `C:\Windows`, or `../x`, always asks. Commands run without a shell on every platform, so `&&`, `|`, `>`, and `$(...)` reach the program as plain text and can't chain a second command, and what the approval check reads is exactly what runs. On Windows, Node won't start `.cmd` and `.bat` programs like `npm` without a shell, so those don't run there. -- **File edits** don't go through approvals. `write_file` and `edit_file` only write inside the clone, and never into `.git`, whose config and hooks decide what git runs. -- **Anything else** pauses the run. The hook defers the call, which ends the run with the call waiting, and the app posts Approve / Deny buttons in the code channel. Your click resumes the Claude Code session, and the hook answers the waiting call with your decision. The paused run is parked in memory with its channel and the ts of the approval message, so a click only resumes the run its buttons were posted for, and buttons left over from a replaced or stopped run show as expired. Sending a new message while an approval is pending skips that command: the next turn answers it as not run before reading your message. That's fine for a single-instance sample. A multi-instance deployment would keep the paused runs, and the Claude Code session transcripts, in a shared store instead. +- **Read-only** commands and **local git changes** run with no prompt. A path outside the clone always asks. Commands run without a shell, so they can't chain a second command, and what the approval check reads is exactly what runs. On Windows, `.cmd` and `.bat` programs don't run, since Node needs a shell to start them. +- **File edits** don't go through approvals. `write_file` and `edit_file` only write inside the clone. +- **Anything else** shows **Approve** and **Deny** buttons in the code channel, and the command runs only if someone in the channel approves it. The agent gets only these tools. Claude Code's built-in tools, like its own `Bash` and `Edit`, are turned off, and so are the settings, `CLAUDE.md` files, and MCP servers configured on the machine running the app. @@ -163,6 +161,7 @@ The Claude Agent SDK runs the Claude Code CLI that comes bundled with it, and th ```sh slack run ``` +
Using the Terminal @@ -258,15 +257,15 @@ node app-oauth.js ### Using the App -Once the agent is running, invite it to a channel by typing `/invite @agent-name` in the message box. +Once the agent is running, there are several ways to interact: -**Channel @mentions** — @mention the agent in a thread with a question about the conversation, like _what did we decide here?_, and it answers in the thread. @mention it with a task and a repo, like _add a "hello world" to the README of ``_, and it replies with a link to a new code channel for the work. +**App Home** — Open the agent in Slack and click the _Home_ tab to see how to start a task. -**Direct messages** — Open the agent's _Messages_ tab and ask a question or describe a task, or pick a suggested prompt. It answers there, or links a code channel for bigger work. +**Direct Messages** — Open the agent's _Messages_ tab and ask a question or describe a task, or pick a suggested prompt. It answers there, or links a code channel for bigger work. -**Code channels** — Follow the work in the new channel. Approve or deny commands as they come up, comment on the Plan tab, review the diff in the code tab, and send follow-ups without an @mention. Say you're done to wrap up and archive the channel. +**Channel @mentions** — Invite the agent to a channel by typing `/invite @agent-name` in the message box, then @mention it in a thread with a question about the conversation, like _what did we decide here?_, and it answers in the thread. @mention it with a task and a repo, like _add a "hello world" to the README of ``_, and it replies with a link to a new code channel for the work. -**App Home** — Open the agent in Slack and click the _Home_ tab to see how to start a task. +**Code Channels** — Follow the work in the new channel. Approve or deny commands as they come up, comment on the Plan tab, review the diff in the code tab, and send follow-ups without an @mention. Say you're done to wrap up and archive the channel. ### Linting @@ -284,6 +283,7 @@ npm run check ### Testing ```sh +# Run unit tests npm test ``` @@ -293,11 +293,9 @@ npm test `manifest.json` is a configuration for Slack apps. With a manifest, you can create an app with a pre-defined configuration, or adjust the configuration of an existing app. -The app requests `code_channels:manage` for the `agents.conversations.*` methods, `chat:write` for `agents.sessions.*` and replies, `canvases:write` for the plan, and `channels:read` / `groups:read` to recognize code channels and hear when they're archived. It receives mentions with `app_mentions:read` and messages with `channels:history` / `groups:history` / `im:history`, and those history scopes plus `mpim:history` let it read the thread or direct message a request came from. `assistant:write`, `im:read`, and `im:write` support the agent's direct-message experience under `agent_view`. - ### `app.js` -`app.js` is the entry point for the application and is the file you'll run to start the server. This project aims to keep this file as thin as possible, primarily using it as a way to route inbound requests. It runs Bolt's `App` in Socket Mode, which handles each event as it arrives, so a long agent turn never holds up the stop button, an approval click, or another channel, and agent slash commands are routed to it without a `slash_command_url`. +`app.js` is the entry point for the application and is the file you'll run to start the server. This project aims to keep this file as thin as possible, primarily using it as a way to route inbound requests. It runs Bolt's `App` in Socket Mode, so a long agent turn never holds up the stop button, an approval click, or another channel, and agent slash commands are routed to it without a `slash_command_url`. ### `app-oauth.js` @@ -325,24 +323,14 @@ Every incoming request is routed to a "listener". This directory groups each lis ### `/agent` -The `agent.js` file defines the routing agent and the coding agent with their tools, and starts and resumes their runs. Along with `guardrails.js` and `tools`, it's the only code that uses the Claude Agent SDK. - -The `prompts.js` file holds both agents' prompts. - -The `turns.js` file runs each turn for the listeners: it answers requests, sets the session status, runs the agent, and posts the outcome or the Approve / Deny buttons. It also queues messages that arrive mid-turn and handles approvals and the stop button. - -The `outcome.js` file defines the `RunOutcome` that `agent.js` returns and `turns.js` reads. - -The `context.js` file reads the thread or direct message a request came from, so the agent can follow the conversation. - -The `guardrails.js` file holds the SDK hooks that gate tool calls: the approval check for `run_command`, which defers a command that needs approval, and the check that skips every tool call once the session is stopped. - -The `sessions.js` file keeps each code channel's session in memory: its working directory, plan canvas, conversation history, and messages waiting for the next turn. It also defines the `AgentDeps` and `RequestDeps` classes passed to the agents at runtime, providing access to the Slack client and the session or request. - -The `approvals.js` file decides which commands need approval and holds runs paused on one. - -The `runtime.js` file holds what the tools share during a run: the shape of a tool's reply. - -The `workspace.js` file splits and runs commands in the clone without the app's secrets, and keeps file tools inside it. - -The `tools` directory contains one file per tool the agents can call. Each exports a function of the run's deps that returns the tool, since the SDK calls a tool with only its arguments. +- `agent.js` — Defines the routing agent and the coding agent with their tools, and starts and resumes their runs. Along with `guardrails.js` and `tools`, it's the only code that uses the Claude Agent SDK. +- `prompts.js` — Holds both agents' prompts. +- `turns.js` — Runs each turn for the listeners: it answers requests, sets the session status, runs the agent, and posts the outcome or the Approve / Deny buttons. It also queues messages that arrive mid-turn and handles approvals and the stop button. +- `outcome.js` — Defines the `RunOutcome` that `agent.js` returns and `turns.js` reads. +- `context.js` — Reads the thread or direct message a request came from, so the agent can follow the conversation. +- `guardrails.js` — Holds the SDK hooks around tool calls: the approval check for `run_command`, which defers a command that needs approval, and the check that skips every tool call once the session is stopped. +- `sessions.js` — Keeps each code channel's session in memory: its working directory, plan canvas, conversation history, and messages waiting for the next turn. It also defines the `AgentDeps` and `RequestDeps` classes passed to the agents at runtime, providing access to the Slack client and the session or request. +- `approvals.js` — Decides which commands need approval and holds runs paused on one. +- `runtime.js` — Holds what the tools share during a run: the shape of a tool's reply. +- `workspace.js` — Splits and runs commands in the clone without the app's secrets, and keeps file tools inside it. +- `tools` — Contains one file per tool the agents can call. Each exports a function of the run's deps that returns the tool, since the SDK calls a tool with only its arguments. diff --git a/openai-agents-sdk/README.md b/openai-agents-sdk/README.md index cda25df..46843f6 100644 --- a/openai-agents-sdk/README.md +++ b/openai-agents-sdk/README.md @@ -1,9 +1,9 @@ # Coding Agent for Slack (Bolt for JavaScript and OpenAI Agents SDK) -A sample Slack **coding agent** built with [Bolt for JavaScript](https://docs.slack.dev/tools/bolt-js/) and [OpenAI Agents SDK](https://openai.github.io/openai-agents-js/) using models from [OpenAI](https://openai.com). When you mention the agent, it decides whether to reply in place or create a dedicated **code channel** for the work. In a code channel it clones a repository into a temp workspace, does real work there, and keeps the channel's plan, context bar, and code tab current as it goes. +A sample Slack agent that showcases [Slack Code](https://docs.slack.dev/ai/slack-code/) built with [Bolt for JavaScript](https://docs.slack.dev/tools/bolt-js/) and [OpenAI Agents SDK](https://openai.github.io/openai-agents-js/) using models from [OpenAI](https://openai.com). Mention it in a channel with a task and a project repo, and it decides whether to answer in place or create a dedicated **code channel** for the work. In a code channel it clones the repo into a temporary workspace and makes changes with the necessary approvals, keeping the channel's plan, context bar, and code tab current as it goes. > [!WARNING] -> **This agent runs commands generated by a language model on the machine running the app.** Only read-only commands and local git changes run without asking. Everything else, including the repo's own tests and builds, needs approval in Slack before it runs (see [Command approvals](#command-approvals)), and anyone in the code channel can approve. Approval is the safety gate, so read each command before you approve it. Commands run without the app's tokens or anything that looks like a credential in their environment. **Only run this sample against trusted, throwaway repositories, and on a machine you're comfortable letting it operate.** It is a reference sample, not a hardened product. +> **This agent runs commands generated by a language model on the machine running the app.** Only run it against trusted repositories on a machine you're comfortable letting it operate. Refer to [Command approvals](#command-approvals) for how command approvals work. ## App Overview @@ -12,7 +12,7 @@ The coding agent works like this: 1. You `@Coding Agent fix the flaky login test in ` in any channel, or send the agent a direct message. 2. The agent decides how to handle it, reading the thread or direct message the request came from. A question gets an answer in place. Work that takes more than one message gets a code channel, created with the `create_code_channel` tool and linked back to your message. 3. Slack seeds the new channel with your request, mention included, and that mention starts the session there, along with the conversation the request came from. The agent clones the repo, pins it to the context bar, writes a plan, and registers a few slash commands for the channel. -4. It reads and edits files with `read_file`, `edit_file`, and `write_file`, which stay inside the clone and never ask. It runs commands with `run_command`: read-only commands (`ls`, `grep`, `git diff`, …) and local git changes (`git switch -c`, `git commit`, …) run immediately; anything else, including tests, asks for your approval first. +4. It reads and edits files and runs other commands in the clone. Riskier commands ask for your approval first. 5. It publishes the diff to the code tab and summarizes what it did. 6. Keep chatting in the channel (no `@`-mention needed), comment on the plan, or use its slash commands to iterate. Messages sent while the agent works go into its next turn together. 7. When you say it's done, the agent posts a summary, which is shared back to your original message, and archives the channel. @@ -38,8 +38,6 @@ Each code channel method is a tool the model calls when it decides to, in [`agen | `read_file`, `write_file`, `edit_file` | Local files in that directory | | `run_command` | A local program in that directory, run without a shell | -`create_code_channel` is the only tool when answering a mention outside a code channel, and the one tool missing inside it, so the agent can't create a channel from a channel. The session status belongs to the session lifecycle rather than the model, so the listeners call `agents.sessions.setStatus` around every turn (`processing` while working, `suspended` while waiting on an approval, `active` when done). Wrapping up is the exception: `archive_channel` sets `closed` itself, right before it archives the channel. - ### Code channel behavior - **Plan as a canvas.** The plan is attached with comment access, so people can comment but only the agent edits. `read_plan` gives the agent open comments each turn, and `setCanvasContent` keeps comments anchored to the sections it didn't change. @@ -56,9 +54,9 @@ Each code channel method is a tool the model calls when it decides to, in [`agen `run_command` is registered with the OpenAI Agents SDK's `needsApproval` hook ([`agent/guardrails.js`](./agent/guardrails.js)), which asks `commandNeedsApproval` in [`agent/approvals.js`](./agent/approvals.js): -- **Read-only** commands like `ls`, `grep`, and `git diff`, and **local git changes** like `git add`, `git commit`, and `git switch -c`, run with no prompt. A path outside the clone, like `/etc`, `C:\Windows`, or `../x`, always asks. Commands run without a shell on every platform, so `&&`, `|`, `>`, and `$(...)` reach the program as plain text and can't chain a second command, and what the approval check reads is exactly what runs. On Windows, Node won't start `.cmd` and `.bat` programs like `npm` without a shell, so those don't run there. -- **File edits** don't go through approvals. `write_file` and `edit_file` only write inside the clone, and never into `.git`, whose config and hooks decide what git runs. -- **Anything else** pauses the run. The app posts Approve / Deny buttons in the code channel; your click resumes the agent with the decision. The paused run is parked in memory with its channel and the ts of the approval message, so a click only resumes the run its buttons were posted for, and buttons left over from a replaced or stopped run show as expired. Sending a new message while an approval is pending skips that command. That's fine for a single-instance sample. A multi-instance deployment would persist `RunState` to a shared store instead, with `state.toString()` and `RunState.fromString()`. +- **Read-only** commands and **local git changes** run with no prompt. A path outside the clone always asks. Commands run without a shell, so they can't chain a second command, and what the approval check reads is exactly what runs. On Windows, `.cmd` and `.bat` programs don't run, since Node needs a shell to start them. +- **File edits** don't go through approvals. `write_file` and `edit_file` only write inside the clone. +- **Anything else** shows **Approve** and **Deny** buttons in the code channel, and the command runs only if someone in the channel approves it. ## Setup @@ -161,6 +159,7 @@ The OpenAI Agents SDK sends a trace of each run, including tool inputs and outpu ```sh slack run ``` +
Using the Terminal @@ -256,15 +255,15 @@ node app-oauth.js ### Using the App -Once the agent is running, invite it to a channel by typing `/invite @agent-name` in the message box. +Once the agent is running, there are several ways to interact: -**Channel @mentions** — @mention the agent in a thread with a question about the conversation, like _what did we decide here?_, and it answers in the thread. @mention it with a task and a repo, like _add a "hello world" to the README of ``_, and it replies with a link to a new code channel for the work. +**App Home** — Open the agent in Slack and click the _Home_ tab to see how to start a task. -**Direct messages** — Open the agent's _Messages_ tab and ask a question or describe a task, or pick a suggested prompt. It answers there, or links a code channel for bigger work. +**Direct Messages** — Open the agent's _Messages_ tab and ask a question or describe a task, or pick a suggested prompt. It answers there, or links a code channel for bigger work. -**Code channels** — Follow the work in the new channel. Approve or deny commands as they come up, comment on the Plan tab, review the diff in the code tab, and send follow-ups without an @mention. Say you're done to wrap up and archive the channel. +**Channel @mentions** — Invite the agent to a channel by typing `/invite @agent-name` in the message box, then @mention it in a thread with a question about the conversation, like _what did we decide here?_, and it answers in the thread. @mention it with a task and a repo, like _add a "hello world" to the README of ``_, and it replies with a link to a new code channel for the work. -**App Home** — Open the agent in Slack and click the _Home_ tab to see how to start a task. +**Code Channels** — Follow the work in the new channel. Approve or deny commands as they come up, comment on the Plan tab, review the diff in the code tab, and send follow-ups without an @mention. Say you're done to wrap up and archive the channel. ### Linting @@ -282,6 +281,7 @@ npm run check ### Testing ```sh +# Run unit tests npm test ``` @@ -291,11 +291,9 @@ npm test `manifest.json` is a configuration for Slack apps. With a manifest, you can create an app with a pre-defined configuration, or adjust the configuration of an existing app. -The app requests `code_channels:manage` for the `agents.conversations.*` methods, `chat:write` for `agents.sessions.*` and replies, `canvases:write` for the plan, and `channels:read` / `groups:read` to recognize code channels and hear when they're archived. It receives mentions with `app_mentions:read` and messages with `channels:history` / `groups:history` / `im:history`, and those history scopes plus `mpim:history` let it read the thread or direct message a request came from. `assistant:write`, `im:read`, and `im:write` support the agent's direct-message experience under `agent_view`. - ### `app.js` -`app.js` is the entry point for the application and is the file you'll run to start the server. This project aims to keep this file as thin as possible, primarily using it as a way to route inbound requests. It runs Bolt's `App` in Socket Mode, which handles each event as it arrives, so a long agent turn never holds up the stop button, an approval click, or another channel, and agent slash commands are routed to it without a `slash_command_url`. +`app.js` is the entry point for the application and is the file you'll run to start the server. This project aims to keep this file as thin as possible, primarily using it as a way to route inbound requests. It runs Bolt's `App` in Socket Mode, so a long agent turn never holds up the stop button, an approval click, or another channel, and agent slash commands are routed to it without a `slash_command_url`. ### `app-oauth.js` @@ -323,22 +321,13 @@ Every incoming request is routed to a "listener". This directory groups each lis ### `/agent` -The `agent.js` file defines the routing agent and the coding agent with their tools, and starts and resumes their runs. It's the only file outside `tools` that uses the OpenAI Agents SDK. - -The `prompts.js` file holds both agents' prompts. - -The `turns.js` file runs each turn for the listeners: it answers requests, sets the session status, runs the agent, and posts the outcome or the Approve / Deny buttons. It also queues messages that arrive mid-turn and handles approvals and the stop button. - -The `outcome.js` file defines the `RunOutcome` that `agent.js` returns and `turns.js` reads. - -The `context.js` file reads the thread or direct message a request came from, so the agent can follow the conversation. - -The `guardrails.js` file holds the SDK hooks around tool calls: the approval check for `run_command`, the guardrail that skips every tool call once the session is stopped, and the error function that tells the model when a tool failed. - -The `sessions.js` file keeps each code channel's session in memory: its working directory, plan canvas, conversation history, and messages waiting for the next turn. It also defines the `AgentDeps` and `RequestDeps` classes passed to the agents at runtime, providing access to the Slack client and the session or request. - -The `approvals.js` file decides which commands need approval and holds runs paused on one. - -The `workspace.js` file splits and runs commands in the clone without the app's secrets, and keeps file tools inside it. - -The `tools` directory contains one file per tool the agents can call. +- `agent.js` — Defines the routing agent and the coding agent with their tools, and starts and resumes their runs. Along with `guardrails.js` and `tools`, it's the only code that uses the OpenAI Agents SDK. +- `prompts.js` — Holds both agents' prompts. +- `turns.js` — Runs each turn for the listeners: it answers requests, sets the session status, runs the agent, and posts the outcome or the Approve / Deny buttons. It also queues messages that arrive mid-turn and handles approvals and the stop button. +- `outcome.js` — Defines the `RunOutcome` that `agent.js` returns and `turns.js` reads. +- `context.js` — Reads the thread or direct message a request came from, so the agent can follow the conversation. +- `guardrails.js` — Holds the SDK hooks around tool calls: the approval check for `run_command`, the guardrail that skips every tool call once the session is stopped, and the error function that tells the model when a tool failed. +- `sessions.js` — Keeps each code channel's session in memory: its working directory, plan canvas, conversation history, and messages waiting for the next turn. It also defines the `AgentDeps` and `RequestDeps` classes passed to the agents at runtime, providing access to the Slack client and the session or request. +- `approvals.js` — Decides which commands need approval and holds runs paused on one. +- `workspace.js` — Splits and runs commands in the clone without the app's secrets, and keeps file tools inside it. +- `tools` — Contains one file per tool the agents can call.