Skip to content

feat: add the team agent to the OpenAI Agents SDK app - #5

Merged
zimeg merged 16 commits into
mainfrom
clack/team-agent-openai
Oct 28, 2026
Merged

zimeg merged 16 commits into
mainfrom
clack/team-agent-openai

Conversation

@zimeg

@zimeg zimeg commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

Summary

This pull request turns the openai-agents-sdk app into a team agent whose runbooks reinforce themselves: the agent writes what channel messages settle into runbooks, then answers from those runbooks next time.

  • Runbooks are canvases titled Runbook: <topic>.
  • Bot-token runbook tools follow the coding agent's tool pattern: list_runbooks (files.list), read_runbook (canvases.getContent), and create_runbook (canvases.create with channel_id). New runbooks are added as a tab in the channel, so the whole team can read and edit them.
  • The Slack MCP Server is optional. When a person has connected it, run_agent() swaps in the MCP Server's runbook tools (search plus canvas read/create/update) so the agent works as them, and only then can it edit an existing runbook section by section. Everyone else gets the bot-token tools.
  • One agent learns as it answers. It answers DMs and @mentions from runbooks, and the message listener runs it on each channel message to learn from. When a run writes a runbook, the message's author gets an ephemeral note with the link. Nothing is posted to the channel.
  • Runs are capped at 50 turns, and a run that hits the cap ends with a message, matching bolt-python-coding-agent.
  • New bot scopes: canvases:read, canvases:write, files:read. I also sorted the bot scope list.

canvases.getContent isn't in slack_sdk (3.45.0 or main) or @slack/web-api yet, so read_runbook calls it with client.api_call. canvases_create also has no typed channel_id, so it goes through **kwargs.

claude-agent-sdk/ and pydantic-ai/ are still the starter agent, and the root README.md/AGENTS.md still describe it. Follow-up PRs bring those to parity.

Known risks:

  • With the Slack MCP Server connected, a crafted message could steer the agent into searching the author's DMs and private channels, or into editing any canvas they can open.
  • Two messages close together are learned from at the same time, which can create two copies of a new runbook.
  • Learning sees only the message itself, not its thread.
  • files.list returning canvases tabbed in channels the bot is in is untested.

Testing

  • Invite the agent to a channel without connecting the Slack MCP Server. Post "Fixed it: rotate the signing secret, then redeploy." Confirm a Runbook: <topic> tab appears in the channel, a teammate can open it, and only you see an ephemeral note with the link.
  • Post small talk and confirm nothing changes and no note appears.
  • @mention the agent with the same problem and confirm it answers from the runbook and links it.
  • Post a correction ("Actually, redeploy before rotating") without the Slack MCP Server connected and confirm no duplicate runbook is created. Connect it and post again, and confirm the existing runbook is updated.
  • With OAuth (app_oauth.py), connect the Slack MCP Server from the Home tab and repeat. Confirm canvas edits show your name.

🤖 Generated with Claude Code

The team agent keeps runbooks current and routes requests. Runbooks are
canvases titled "Runbook: <topic>" that the agent reads and writes
through the Slack MCP Server. Quiet channel threads get a tool-less
check, and threads worth keeping get an "Add to runbook" button that
saves the thread as the person who clicked.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
@zimeg zimeg added enhancement M-T: A feature request for new functionality new PR only - a new app is being introduced semver:minor Use on pull requests to describe the release version increment labels Oct 26, 2026
@zimeg zimeg self-assigned this Oct 26, 2026
zimeg and others added 15 commits October 26, 2026 16:35
…essage

The OpenAI Agents SDK stops a run after 10 turns by default, which tool
heavy requests and runbook saves can reach. Both agents now pass
max_turns=50 with a max_turns error handler, matching
bolt-python-coding-agent. A save that changes nothing keeps the Add to
runbook button so it can be retried.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
The same agent that answers from runbooks now writes them. Quiet threads
are reviewed with the last connected replier's token, a restricted set
of Slack MCP tools, and a guardrail that keeps searches to runbook
files in channels. The person the review ran as gets an ephemeral note
when a runbook changed. The Add to runbook button and the separate
check and save agents are gone.

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

Canvases created through the Slack MCP Server are standalone, and search
only finds them when DMs and group DMs are included. Requiring public
and private channels hid every runbook the agent wrote. The guardrail
now only checks for a files search with the keyword Runbook.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
…g for quiet threads

Each channel message from a connected user now gets one review by the
same agent, with its thread as context and the author's token. That
drops the quiet-period timer, the per-thread token memory, and
RUNBOOK_SETTLE_SECONDS, and the edit and the ephemeral note go to the
person who wrote the message.

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

The agent module now reads in definition order with run_agent last, and
the instructions and out-of-turns handler are inline. Without a user
token there is no Slack MCP Server and no runbooks, so the mention and
message listeners now ask the person to connect instead of running the
agent.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
The message listener now runs the agent on each channel message from a
connected user directly, and posts the ephemeral note when the run
wrote a canvas. The runbooks package and run_review are gone: every run
gets the same Slack MCP runbook tools and search guardrail.

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

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
The agent runs with the bot token again, using list_runbooks,
read_runbook, and write_runbook (files.list, canvases.getContent,
canvases.create, and canvases.edit), following the coding agent's tool
pattern. New runbooks are added as a tab in the channel. People who
connect the Slack MCP Server get its runbook tools as themselves
instead. canvases.getContent isn't in slack_sdk yet, so read_runbook
calls it with api_call.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
…he Slack MCP Server

With the bot token the agent now only lists, reads, and creates
runbooks. Editing an existing runbook happens through the Slack MCP
Server's canvas tools, which update it section by section, so the bot
no longer replaces a whole canvas.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
…er reuses closed connections

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
@zimeg
zimeg marked this pull request as ready for review October 28, 2026 01:39

@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.

🐙 Merging this now after testing shows promise of runbooks that can be edited without a particular callout. The models are good.

Comment on lines +19 to +21
response = deps.client.api_call(
"canvases.getContent", params={"canvas_id": canvas_id}
)

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're implementing this now here: slackapi/python-slack-sdk#1999

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 new PR only - a new app is being introduced semver:minor Use on pull requests to describe the release version increment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant