Skip to content

feat: replace the starter agent with the coding agent sample - #5

Merged
zimeg merged 22 commits into
mainfrom
coding-agent
Oct 16, 2026
Merged

zimeg merged 22 commits into
mainfrom
coding-agent

Conversation

@zimeg

@zimeg zimeg commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Summary

This pull request replaces the starter agent template contents with a coding agent sample built on the OpenAI Agents SDK.

  • Mentions and direct messages get an answer in place, or a code channel when the work takes more than one message. A small routing agent decides with a create_code_channel tool, reading the thread or direct message the request came from.
  • In a code channel the agent clones the repo, writes its plan to a commentable Plan tab, edits files, runs commands, publishes a diff to the code tab, registers slash commands for the channel, and archives the channel with a summary when done. A new channel's first turn gets the conversation it was started from.
  • File edits stay inside the clone and never ask. Read-only commands and local git changes like git commit run right away. Running the repo's code and paths outside the clone post Approve / Deny buttons. Commands run without a shell, so && and | reach the program as plain text, and without the app's secrets in their environment.
  • Runs on Bolt's AsyncApp, so a long turn never holds up the stop button, an approval click, or another channel. Messages sent while the agent works go into its next turn together. Stopping, or archiving the channel from Slack, keeps a running turn from calling more tools.
  • Agent slash commands arrive over Socket Mode, or at the manifest's code_channels.slash_command_url when running over HTTP with app_oauth.py.
  • Listeners import only from the agent package, and the OpenAI Agents SDK stays in agent/agent.py, agent/guardrails.py, and agent/tools/, so other frameworks can follow the same structure. The root AGENTS.md lists what implementations keep the same, including what the framework side keeps true for agent/turns.py.
  • Removes the claude-agent-sdk/ and pydantic-ai/ starter implementations and the .claude/ directory, including the Bolt vendoring commands, and the maintainers guide.
  • Narrows the ruff and tests matrices and dependabot to openai-agents-sdk/, tests Python 3.14, pins workflow actions, and checks dependencies daily with a cooldown outside of Slack packages.

Testing

  • Copy openai-agents-sdk/.env.sample to .env, set OPENAI_API_KEY, and start the app with slack run from openai-agents-sdk/.
  • Open the agent's Messages tab and confirm the suggested prompts appear. Ask a question and confirm it replies in the direct message, then ask for a change to a throwaway repo and confirm it links a new code channel.
  • In a thread, mention the agent with a question about the thread, like "what did we decide here?", and confirm it answers from the thread without creating a channel.
  • In a thread, mention it with a task on a throwaway repo, like adding "hello world" to a README, and confirm a code channel is created with a pointer in your thread and the first turn knows the thread's context.
  • In the code channel, confirm the agent edits files and commits without asking, then approve its test or build command and confirm the diff appears in the code tab. Deny a later command and confirm the agent carries on without running it.
  • Run one of the agent's slash commands, like /run-tests, and confirm it starts a turn. Repeat over HTTP with app_oauth.py after setting the ngrok domain in manifest.json.
  • Send two messages quickly while the agent works and confirm they're answered together in its next turn.
  • Ask for a plan and confirm a Plan tab appears instead of a plan in a message.
  • Press stop mid-turn and confirm the agent says it stopped, posts nothing more from that turn, and picks back up on your next message.
  • Archive a code channel from Slack while a turn runs and confirm the agent posts nothing more there.
  • Say the work is done and confirm the summary is shared back to your original message, the session closes, and the channel is archived.

🤖 Generated with Claude Code

zimeg and others added 22 commits October 8, 2026 11:20
Replaces the starter agent template contents with a coding agent built
on the OpenAI Agents SDK. Mentions either get an answer in place or a
code channel where the agent clones a repo, plans in a canvas, makes
changes with command approvals, and publishes a diff.

Removes the claude-agent-sdk and pydantic-ai starter implementations
and the .claude directory, adds AGENTS.md files, and narrows CI and
dependabot to openai-agents-sdk.
…k-agnostic

Listeners now import only from the agent package. The OpenAI Agents SDK is
confined to agent/agent.py and the tools, and agent/turns.py runs turns,
approvals, and stops without importing it, so another framework can reuse
listeners/ and turns.py as they are.

Only read-only commands inside the clone run without asking. Shell syntax,
paths that leave the clone, and running the repo's own code all ask first.
Clones accept only remote URLs and check out symlinks as plain files.

A newer message retires a pending approval so a late click can't resume an
older run. Stopping skips every tool call through a tool input guardrail.
A failed turn leaves processing, and running out of turns ends with a
message. The diff compares against the cloned commit and includes new files.
…rns async

Moves the app to Bolt's AsyncApp so a long turn never holds up the stop
button, an approval click, or another channel. Messages that arrive while
a turn runs wait and go into the next turn together, labeled with who sent
them.

Direct messages are answered like mentions. Requests from a thread or a
direct message bring that conversation to the agent, and a new code
channel's first turn gets the conversation it was started from. Messages
and slash commands pick up code channels the app forgot after a restart.

Adds read_file, write_file, and edit_file tools that stay inside the clone
and never write into .git, and lets local git changes like add, commit, and
switch -c run without asking. Commands run without the app's secrets, and
their output keeps its end, where test failures are.

Long sessions drop their oldest conversation instead of outgrowing the
context window. Runs end once a channel is created or archived. Prompts
and the run outcome move to their own modules, and tests drive real agent
runs with a scripted model.

Adds suggested prompts, pins CI actions, tests Python 3.10 and 3.14, adds
a Dependabot cooldown outside of Slack packages, and stops auto-merging
0.x minor updates.
# Conflicts:
#	claude-agent-sdk/pyproject.toml
#	claude-agent-sdk/requirements.txt
#	openai-agents-sdk/pyproject.toml
#	openai-agents-sdk/requirements.txt
#	pydantic-ai/pyproject.toml
#	pydantic-ai/requirements.txt
Replaces run_shell and run_git with one run that starts a program
directly, finding it on PATH so npm resolves to npm.cmd on Windows.
run_command splits a command into arguments the same way the approval
check does, so what's checked is exactly what runs, and takes a
directory instead of cd.

Shell syntax no longer needs its own rule since it reaches the program as
plain text. The outside-the-clone check also catches drive letters,
backslashes, and UNC paths.
Apps running over HTTP need code_channels.slash_command_url for agent
slash commands to arrive. Renames agent/store.py to agent/sessions.py
after the sessions it holds, and brings comments up to date with where
turns, approvals, and the SDK now live.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Moves AgentDeps and RequestDeps from agent/deps.py into agent/sessions.py,
next to the CodeChannelSession a turn runs in, and drops their unused
user_id. The model already sees who sent each message in the text.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Discarding a session now marks it archived and stopped, so a turn still
running calls no more tools and doesn't put the session back with a
deleted clone when it finishes.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

@zimeg zimeg left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗣️ Handfuls of comments with a working sample that'll be nice to revisit so I'll merge to iterate more focused.

"is_enabled": true,
"request_url": "https://ngrok-free.app/slack/events"
},
"is_mcp_enabled": true,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🪬 note: For now we omit these capabilities for more focused experience within this sample.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤡 note: This tool is used even though it is a significant enhancement to examples but I'm hoping for now to focus on code channel creation and follow up with improvements like this!

try:
response = deps.client.agents_conversations_setView(
channel_id=deps.channel_id,
type="html",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
type="html",
type="block_kit",

🧱 note: At the moment we don't include a Block Kit view tool but we can follow up and extend this as cases arrive.

Comment on lines +18 to +31
icon: (
Literal[
"branch",
"folder",
"hierarchy",
"life-ring",
"link",
"globe",
"terminal",
"code",
"search",
"lock",
]
| None

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔭 note: We find this list from reference but keep all of these "informative" instead of handling actions at this time.

🔗 https://docs.slack.dev/ai/slack-code/code-channel-properties#context-bar-items

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📚 note: Will update after landing adjacent frameworks!

Comment on lines +16 to +26
async def run_command_needs_approval(_ctx, arguments: dict, _call_id: str) -> bool:
"""The `needs_approval` hook for `run_command`, checked with its arguments before it runs.

Returning True pauses the run with a ToolApprovalItem, which `agent/turns.py`
posts as Approve / Deny buttons.
"""
command = (arguments or {}).get("command", "")
needs = command_needs_approval(command)
if needs:
logger.info("run_command needs approval: %s", command)
return needs

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👽 note: I'm uneased about not including this with tooling but it keeps patterns more separate and framework logic of agent contained!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧪 note: Will reasses test patterns after landing other frameworks but want to have this now for comparison.

@zimeg
zimeg marked this pull request as ready for review October 16, 2026 03:27
@zimeg
zimeg merged commit 2e86b5d into main Oct 16, 2026
3 checks passed
@zimeg
zimeg deleted the coding-agent branch October 16, 2026 03:28
@zimeg zimeg self-assigned this Oct 16, 2026
@zimeg zimeg added the enhancement M-T: A feature request for new functionality label Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement M-T: A feature request for new functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant