Slack

Connect Slack to your organization, enable agents, assign channel residents, and understand how Slack channels and reply threads map into ArchAstro.

Documentation status: Beta. This guide reflects the current Slack integration model, but its organization and setup instructions may change as we validate the workflows with more organizations.

Overview

Slack has two credential models and one routing layer:

What you need Use Identity in Slack
One agent acts through one person's Slack account integration/slack The connected person
Agents participate as the organization's Slack app Org slack_bot integration plus enablement/slack_bot The Slack bot, labeled as the replying agent when permitted
One enabled agent owns a channel's incoming conversation SlackChannelBinding The channel's resident agent

Most team deployments should use the shared Slack bot. Use personal OAuth only when acting as a specific person is intentional.

Slack integration model showing personal OAuth, the shared organization bot, agent enablement, and channel bindings

Understand the four relationships

Slack setup becomes much easier when each relationship has a distinct name:

  1. Slack workspace install — an org admin authorizes the ArchAstro Slack app once. This creates the shared slack_bot integration and stores the bot credential.
  2. Agent enablement — an enablement/slack_bot installation lets one agent use that shared bot connection.
  3. Channel binding — a SlackChannelBinding makes one agent the resident for a channel, optionally binding that channel to a network.
  4. Mirror thread — incoming Slack messages are represented in a thread in ArchAstro so the agent can reason and reply.

Installing the workspace app does not by itself assign a resident to every channel. Likewise, a channel binding does not replace the agent's Slack enablement.

Choose a tutorial

Goal Start here
Let agents answer mentions and DMs as a bot Tutorial 1: install the shared Slack bot
Let an agent read and act as one person Tutorial 2: connect personal Slack OAuth
Make an agent the default resident in an internal channel Tutorial 3: assign an internal channel resident
Put an agent in a customer or Slack Connect channel Tutorial 4: bind a channel to a network
Add your agent while you are a guest in another company's workspace Guest-hosted channels
Understand follow-ups in Slack reply threads Slack reply threads

Tutorial 1: install the shared Slack bot

Use this model when agents should participate under your organization's Slack app rather than impersonating a person.

Before you begin

You need:

  • ArchAstro organization-admin access
  • permission to install apps in the target Slack workspace, or a Slack admin who can approve the request
  • an existing agent
  • a channel where you can invite and test the bot

For agents that respond to incoming conversations, the agent also needs:

  • a unique lookup_key, used as its addressable handle
  • an active thread.session.join participate routine

Step 1: connect the workspace

  1. Sign in to the developer portal as an organization admin.
  2. Select the target app and organization, then open My Org → Integrations.
  3. On the Slack card, select Enable.
  4. Choose the Slack workspace and approve the requested permissions.
  5. Return to the portal and confirm that Slack shows Connected.

Organization integrations page with Slack available to enable

This is a one-time OAuth operation for the organization. It creates a shared integration with provider slack_bot; it does not create a separate bot token for every agent.

Step 2: choose permissions

The default installation requests the complete supported permission set. Customize permissions lets an administrator trim optional scopes before OAuth.

Capability Slack scopes
Receive mentions and send replies app_mentions:read, chat:write — required
Use each agent's name and avatar on replies chat:write.customize
Read public channels channels:read, channels:history
Read private channels the bot has joined groups:read, groups:history
Create or manage private channels groups:write
Receive direct messages im:read, im:history
Read shared files files:read
Match Slack users to ArchAstro accounts users:read, users:read.email
Inspect the workspace team:read
Invite another workspace to a Slack Connect channel conversations.connect:write

If you omit a permission, capabilities that require it remain unavailable. Reopen Settings → Integrations and select Update permissions when requirements change.

Step 3: enable the agent

Attach the agent to the organization's shared Slack bot:

archastro create agentinstallation \
  --agent <agent_id> \
  --kind enablement/slack_bot

When exactly one Slack bot integration matches the agent's organization, the installation auto-binds and becomes active. If more than one matches, select the intended ArchAstro integration:

archastro list integrations \
  --provider slack_bot \
  --auth-type app_installation \
  --org <org_id>

archastro create agentinstallation \
  --agent <agent_id> \
  --kind enablement/slack_bot \
  --shared-integration <integration_id>

<integration_id> is the ArchAstro integration resource ID. It is not the Slack workspace ID that starts with T.

For config-managed agents, include the enablement in the AgentTemplate:

lookup_key: releases

routines:
  - name: Participate in conversations
    event_type: thread.session.join
    handler_type: preset
    preset_name: participate
    status: active

installations:
  - install_type: enablement/slack_bot
    config: {}

Deploying this template creates the same agent-level enablement. The participate routine is what lets the agent wake when it joins a mirrored conversation.

Step 4: invite the app to a channel

In Slack, open the target channel and invite the ArchAstro app. For example:

/invite @ArchAgent

Slack controls channel access. The bot cannot read private-channel history or post into a channel it has not joined, regardless of its ArchAstro installation state.

Step 5: verify the installation

archastro list agentinstallations --agent <agent_id>
archastro describe agentinstallation <installation_id> -o json

Expected result:

  • kind is enablement/slack_bot
  • state is active
  • shared_integration identifies the org Slack bot connection
  • no next_action or setup error remains

If the installation stays pending with next_action: configure_shared_integration, the shared workspace connection is missing, invisible to the current viewer, or ambiguous.

Step 6: test the unbound routing path

In a channel with no resident binding, try:

@ArchAgent @releases What shipped today?

The first mention addresses the Slack app. The second handle selects the agent by lookup_key. Without a recognized agent handle, the concierge handles the message.

Also test a direct message to the app. If a DM or mention arrives but no reply is posted, use the troubleshooting checklist.

To make the agent the channel's default resident, continue to Tutorial 3 for an internal channel or Tutorial 4 for a customer-facing channel.


Tutorial 2: connect personal Slack OAuth

Use integration/slack when an agent should use one person's Slack access and act as that person. This connection is not the workspace bot and does not make the agent the receiver for @ArchAgent mentions.

Typical uses include:

  • searching channels the connected person can access
  • importing that person's Slack activity as context
  • taking an explicitly authorized action through that person's account

Step 1: create the personal installation

archastro create agentinstallation \
  --agent <agent_id> \
  --kind integration/slack

Save the returned installation ID.

Step 2: complete OAuth

archastro authorize agentinstallation <installation_id>

Open the authorization URL and sign in as the person whose Slack identity the agent should use. Review the workspace and permissions before approving.

Step 3: activate and verify

archastro activate agentinstallation <installation_id>
archastro describe agentinstallation <installation_id>

The installation should report active. If the token expires or Slack revokes access, authorize it again rather than replacing the agent.

Personal OAuth versus the shared bot

Behavior Personal integration/slack Shared enablement/slack_bot
Credential belongs to One Slack user The organization Slack app
Slack identity The connected person Bot, optionally customized with agent name/avatar
Reusable by several agents No Yes, with one enablement per agent
Receives app mentions and bot DMs No Yes
Supports resident channel routing No Yes
Good default for team agents No Yes

The two models can coexist on the same agent, but use that deliberately: tools and routines should make it clear whether an action uses the person's account or the bot.


Tutorial 3: assign an internal channel resident

A resident is the default agent for an internal Slack channel. Once assigned, ordinary incoming messages route to that agent; users do not need to include its handle every time.

The generic developer CLI does not currently expose the internal, no-network resident assignment as a first-class command. The runtime operation is slack.channel_bindings.assign, used by a deployed Slack management workflow.

For a product-managed experience, deploy a slash-command or interactivity workflow that calls:

let bindings = import("slack.channel_bindings")

unwrap(bindings.assign({
  slack_team_id: input.slack_team_id,
  channel_id: input.channel_id,
  agent_user_id: input.agent_user_id
}))

The operation creates a bare internal binding when needed and enforces private-channel membership and Slack Connect safety checks. Use slack.channel_bindings.remove_agents to clear the resident without deleting the binding.

How internal routing works

  • A channel with a resident routes to that resident.
  • A channel without a resident falls back to the concierge and explicit agent handles.
  • Assigning a resident is channel-level; it is not scoped to one Slack reply thread.
  • A private channel remains governed by Slack membership and the synchronized mirror-thread membership.

Tutorial 4: bind a channel to a network

Use a network-bound channel for a customer relationship or Slack Connect channel. The binding does three jobs:

  • associates the Slack channel with the ArchAstro network
  • limits the channel to the selected resident agent
  • enrolls the selected agent in the underlying API team, which supplies the privacy boundary for mirrored messages

Externally shared channels fail closed when they are not bound to a network. This prevents an unscoped concierge or arbitrary agent from answering across a company boundary.

Find the Slack workspace and channel IDs

You need IDs only when using the portal form, CLI, API, or a custom workflow.

To copy the channel ID in Slack desktop or web:

  1. Open the target channel.
  2. Select the channel name in the conversation header.
  3. Open About.
  4. Scroll to the bottom and select Copy channel ID.

Channel IDs normally begin with C. The ID is stable even if someone renames the channel. Slack's API also returns channel names and IDs from conversations.list when you need to look them up programmatically.

Slack channel ID walkthrough showing the channel header, About tab, and Copy channel ID action

The CLI's --slack-team value is Slack's workspace ID, historically named team_id; it normally begins with T. Read it from the connected org integration rather than guessing from the company name:

archastro list integrations \
  --provider slack_bot \
  --auth-type app_installation \
  -o json

Find the record for the target Slack workspace and copy its installation_id. That is the <T...> value used by --slack-team. The integration's ArchAstro resource id is a different identifier and must not be substituted.

Option A: connect from the portal

The portal and API use the same SlackChannelBinding resource. If your app exposes the network connection UI, open the network's Connection tab, select Connect Slack channel, enter the Slack channel ID, and choose the resident agent.

Option B: connect from the CLI

archastro create slackchannelbinding \
  --slack-team <T...> \
  --channel <C...> \
  --team <team_id> \
  --agent <agent_id> \
  --customer-label "Acme"

In user-facing prose, <team_id> is the network ID. The CLI and API retain the underlying team name.

The command is an idempotent upsert. Repeat --agent only when a workflow intentionally permits several attached agents; the normal resident model uses one.

Inspect the result:

archastro list slackchannelbindings --team <team_id>

archastro describe slackchannelbinding <C...> \
  --slack-team <T...>

Remove the binding:

archastro delete slackchannelbinding <C...> \
  --slack-team <T...>

Deleting a binding stops resident routing for that channel. It does not uninstall the organization Slack app or delete the agent's Slack enablement.

Guest-hosted channels

Being a guest in another company's Slack workspace gives your human account access to a channel. It does not give your organization's Slack app or agents access to that workspace.

There are two supported topologies:

Channel topology Slack app to use
The channel is hosted only in the other company's workspace Install or approve your organization's Slack app in that host workspace
The channel is shared to your workspace with Slack Connect Use the Slack app installation on your side of the shared channel

For a channel hosted only in the other company's workspace:

  1. Connect that workspace from your ArchAstro organization's Settings → Integrations flow.
  2. Have a Slack administrator for the host workspace approve or complete the app installation if your guest account cannot install apps.
  3. Ask a channel member to invite the Slack app to the channel.
  4. Add enablement/slack_bot to the agent.
  5. Bind the channel to a dedicated customer network and the agent, using the host workspace's T… ID and the channel's C… ID.
archastro create slackchannelbinding \
  --slack-team <host-workspace-T...> \
  --channel <channel-C...> \
  --team <customer-network-team_id> \
  --agent <agent_id> \
  --customer-label "Customer name"

Use a network-bound customer binding for this topology. Do not use a bare internal-channel assignment merely because Slack considers the channel internal to the host workspace: people from another company can read the surface, so it needs the customer privacy boundary and guarded reply path.

For Slack Connect, bind the installation that receives events on your side of the shared channel. The same Slack channel can have a separate installation and binding for each participating organization; one organization's binding does not grant credentials or agent access to the other.

If the host will not approve the Slack app and the channel is not shared into your workspace with Slack Connect, you cannot add a resident agent to it. Personal integration/slack OAuth can let an agent act through your user account, but it does not install the bot, receive app mentions, or create channel residency.


Agent names and Slack identity

One shared Slack app can represent many agents. The names serve different purposes:

Name Example Where it appears How to change it
Slack app name ArchAgent App directory, DMs, and the outer @ArchAgent mention Slack app configuration; changes the shared app for every agent
Agent display name BigQuery Buddy Sender name on new replies and thinking indicators Agent name
Agent routing handle bigquery-buddy /archagent assign @bigquery-buddy and explicit agent addressing Agent lookup_key
Thread title #data-platform ArchAstro conversation list Thread metadata; independent of the agent name

For a config-managed agent, set both the human-readable name and stable routing handle in its AgentTemplate:

kind: AgentTemplate
name: BigQuery Buddy
lookup_key: bigquery-buddy

Deploy the config through your normal config workflow. For a directly managed agent, update it from the CLI:

archastro update agent <agent_id> \
  --name "BigQuery Buddy" \
  --lookup-key bigquery-buddy

Optionally update its Slack-facing avatar at the same time:

archastro update agent <agent_id> \
  --profile-picture ./bigquery-buddy.png

Slack displays the agent's name and avatar through per-message username and icon_url overrides. The organization Slack installation must include chat:write.customize; otherwise Slack falls back to the shared app identity. Grant it from Settings → Integrations → Slack → Update permissions.

The change applies to new replies and new thinking indicators. Existing Slack messages keep the identity with which they were posted, and renaming the agent does not rename existing ArchAstro threads.

After changing the handle, use the new value for assignment:

/archagent assign @bigquery-buddy
/archagent status

Slack reply threads

A Slack channel binding applies to the channel, not to one reply thread inside that channel.

Slack channel routing diagram showing channel-level residency and reply placement using thread timestamp

When a person replies in a Slack thread:

  • Slack's thread_ts is preserved so the bot response is posted back into the same visible Slack thread.
  • The channel's resident still determines which agent receives the message.
  • The mirrored ArchAstro conversation is currently channel-level. Separate Slack reply threads in the same channel are not separate agent-context containers.

This distinction matters for concurrent workflows. If two independent requests are active in different Slack reply threads, include a request identifier or other correlation data until per-reply-thread context isolation is enabled.

There is no separate “install agent into this Slack reply thread” operation. Install the bot, enable the agent, then bind the channel or address the agent by handle.

Routing reference

Channel state Receiver Handle behavior
Bound to a network Network's resident agent Resident wins; explicit handle does not reroute
Bound to an internal resident Internal resident agent Resident wins; explicit handle does not reroute
No resident binding Named agent, otherwise concierge @handle selects an enabled agent

Incoming Slack messages are mirrored into ArchAstro. The agent's participate routine produces a reply, and the Slack response forwarder posts it using the shared bot credential. Bot-originated echoes are suppressed to prevent reply loops.

Proactive messages from scripts

An agent with an active enablement/slack_bot can post from a script without managing a webhook URL or token:

let slack = import("slack")

unwrap(slack.send({
  channel: "#release-alerts",
  text: "Release 2.4 is ready for verification."
}))

Reply inside an existing Slack thread by supplying thread_ts:

unwrap(slack.send({
  channel: "C0123456789",
  thread_ts: input.thread_ts,
  text: "The rollback completed successfully."
}))

The bot must be a member of the destination channel and have the necessary Slack scopes.

Troubleshooting

The agent installation is pending

Run:

archastro describe agentinstallation <installation_id>
archastro list integrations --provider slack_bot --auth-type app_installation --org <org_id>
  • No shared integration: an org admin must complete the Slack install.
  • Several shared integrations: recreate or update the enablement with --shared-integration <integration_id>.
  • Integration is invisible: confirm the agent and integration belong to the same app and organization.

Mentions arrive but the agent does not answer

Check, in order:

  1. The Slack app is invited to the channel.
  2. The agent has an active enablement/slack_bot installation.
  3. The agent has a unique lookup_key and active participate routine.
  4. The deployed Slack reply workflow is present for the app.
  5. The channel binding points to the expected resident.
  6. The Slack install includes the scopes required for that channel type.

The agent answers, but Slack receives nothing

  • Confirm chat:write is granted.
  • Confirm the app is still a member of the channel.
  • For customized agent identity, confirm chat:write.customize is granted.
  • Inspect the agent's Slack enablement; replies do not fall back to an unrelated org credential.

A Slack Connect channel is rejected

Externally shared channels require a network-bound SlackChannelBinding before a resident can be assigned. Use /archagent setup <CustomerName> where available, the network Connection UI, or create slackchannelbinding.

A private channel cannot be changed

Private-channel residency is member-managed. Ask a Slack member of that channel with the necessary ArchAstro permissions to perform the assignment.

Users cannot see the mirrored conversation

Slack and ArchAstro identities must be linked for personal visibility. The bot needs users:read and users:read.email for email matching, or the user can link their account from the Slack App Home tab where available. Slack membership remains the source of truth for private-channel visibility.

Remove or rotate Slack access

  • Delete a channel binding to stop routing one channel.
  • Delete an agent's enablement/slack_bot to remove that agent's bot access.
  • Disconnect the org Slack integration only when you intend to affect every agent that uses it.
  • Reconnect or update permissions when rotating the workspace install; then verify each enablement returns to active.
  • Delete personal integration/slack installations individually when a person's access should no longer be used.

Next steps

  1. Read Integrations for the shared-app and personal-OAuth models across providers.
  2. Read Installations for state and lifecycle details.
  3. Read Organizations for the ownership and permission boundary behind integrations.
  4. Read Scripts and the Script language reference to automate Slack actions.