Product

Everything it does, once it is in the channel.

No new place for the team to go, nothing to migrate, and no screen anybody has to learn. It is a member of the channel that happens to be able to read your documents and call your services.

Threads & streaming

The thread is the unit of conversation.

Mention it in a channel it has been invited to, or DM it. Follow-ups in a thread it is already active in need no mention. The DM view is a proper Slack assistant pane with suggested prompts, and each DM thread is titled from its first message.

Slack is the source of truth: the whole thread is rebuilt from Slack on every turn, so edits and deletions are noticed and recorded rather than quietly persisting in a private copy of your workspace. Long threads are windowed — the most recent messages go to the model verbatim and the older part is condensed into a running summary kept on the session.

Answers stream in while a status line says what it is doing. Reply stop — or cancel, never mind — and it cancels the model call and every tool in flight, closes the half-written reply with Stopped by @you, and drops anything the turn was holding. What it spent before you stopped it is still recorded.

Answers over about 3,500 characters arrive as a short lead plus a Markdown file, rather than as a wall of text nobody in the channel will read.

eng-oncall

Sam9:12 AM

@attest_tag checkout errors are up since this morning’s deploy — what changed?

attest_tag replied in #eng-oncall: Two things landed at 08:40 UTC. Sentry opened a new group one minute later — TypeError: cannot read ‘currency’ — 412 events, all on POST /checkout/confirm. That is the same minute #2841 “drop legacy currency fallback” merged. The PR removes the ?? "USD" default in priceFor(), and three call sites still hand it a cart with no currency set. Want me to fix it and raise a PR? Ran on z-ai/glm-5.3-flash — 3.4k in, 512 out, $0.0021. Opening the pull request is a write, so it stopped there and waited for a human to confirm or cancel it.

And there it stops. Reading was free; opening the PR is a write, so it waits for a human — you.

One mention. Two services queried, the credentials for both injected outside the model, and the whole turn priced at two tenths of a cent.

Native tools

The tools it has before you connect anything.

These need no credentials and no setup beyond inviting the bot. The system prompt forces the obvious cases rather than hoping: “check our docs” must call search_docs and answer only from what comes back, “search the web” must call web_search, and “what happened in this channel” must call read_channel_history.

read_thread read_channel_history
Thread and channel messages with names resolved — and only for conversations the person asking is themselves in.
slack_search list_channels list_pins get_user
Workspace search across public channels, the channel list, pinned items, and user lookup.
search_docs
Retrieval over the documents you indexed. “Check our docs” forces this tool and an answer only from what it returns.
web_search fetch_url
Search and page fetch behind an SSRF guard — no private, loopback or link-local hosts, no non-HTTP schemes.
create_artifact
Writes a file and posts it in the thread: md, txt, csv, json, yaml or html, up to 1 MB.
remember recall forget
Facts kept per channel and added to every future turn there.
create_routine list_routines delete_routine
Scheduled prompts that answer in a fresh thread on cron, in your timezone.
http_request + named packs
Connected services, through the proxy. Never with a credential the model can read.
use_connection
Loads a remote MCP server's tools into the turn on demand, instead of spending 20k tokens on definitions every round.
start_fix_job
Hands a code change to the worker container. Offered only where a repository is connected.

Documents

Answers from your own writing, with the page named.

Point it at a folder or a bucket. Documents are chunked at about 500 tokens — each chunk keeping its nearest heading, so a retrieved passage still knows which section it came from — embedded, and stored alongside everything else. Indexing runs on start, every six hours, on !ingest, and whenever you reindex from the console.

A document can be scoped to a single channel, so the support handbook is not answerable from the engineering channel. Plain-text documents can be edited in place in the console.

people-ops

Mei4:07 PM

@attest_tagwhat’s our policy on carrying leave into the next year? check our docs

attest_tagApp4:07 PM

Up to 5 days carry into Q1 and expire on 31 March. Anything above 5 needs your manager’s sign-off before 15 December, and contractors are out of scope entirely.

  • Employee handbook§4.2 Annual leave
  • 2026 policy updateCarry-over changes
Answered only from what you indexed — and it says which page.

Artifacts

Ask for it as a file, and a file is what arrives.

Ask for an export, a report, “send that as CSV”, and it writes the content in full, uploads it to the thread as md, txt, csv, json, yaml or html, and replies with one line and a link instead of repeating the contents into the channel.

Every artifact is kept. The console lists what has been produced, with the channel and the person it was made for, and can open it in Slack, download it, or delete it. That download route always serves an attachment and never renders — the content is model-written and the console origin holds the admin session.

Memory & routines

It remembers, and it shows up on time.

Say remember for this channel: the release captain rotates weekly and the fact is stored and added to every future system prompt there. Memories saved in a public channel are shared across the workspace; memories from a private channel or a DM stay in that conversation.

Say every weekday at 9am post a digest of #support and it creates a cron routine that answers the prompt in a fresh thread at that time, in the configured timezone, and updates its own post in place with the result. The console can edit a routine, run it now, disable it, or delete it.

@attest_tag remember for this channel: the release captain rotates every Monday

Saved. Added to every future turn in #eng-oncall.

Public channel — shared workspace-wide. From a private channel or a DM it stays there.

@attest_tag every weekday at 9am post a digest of #support

Routine created — weekdays, 09:00 Asia/Kathmandu.

Runs in a fresh thread and edits its own post with the result.

Fix jobs

“Fix this and raise a PR” — and it does.

In a thread where it has already worked out what is wrong, it can hand the change to a worker: a brief saying what to change, the evidence it gathered — log lines, stack traces, the ticket, the tool results from this thread — and what done looks like.

The brief is held like any other write. The Confirm card states the repository, the base branch, the change, and the rule the worker runs under: it may push one new branch and open one draft pull request, and it never merges or pushes to the base branch.

Confirm starts a job in a separate container whose environment holds only the job id, the bot’s URL, and a single-use token. It claims the spec and the repository token back over the API, clones the base branch — token in an HTTP header, never in argv, the remote URL, or on disk — runs the tests, makes the change, runs them again, pushes a branch and opens a draft pull request. The PR body carries the brief, the evidence, the files changed and the tests before and after, with an honest note on top when the tests still fail or none were found.

One checklist message in the thread is edited as events arrive. stop, !job cancel, or the console’s Cancel end a job, and the worker pushes nothing further. Jobs survive a restart, because their state lives in the database rather than in memory.

eng-oncall

Priya9:14 AM

yes please — raise it as a draft against main

attest_tagApp9:14 AM

Fix job #f-4172 · acme/storefront

  • clone
  • tests baseline
  • fix
  • tests
  • pull request

It may push one branch and open one draft PR. It never merges, and never pushes to main.

A separate container, a single-use token, one new branch — and a draft PR at the end of it.

Models & cost

A cheap model for most things, a heavy one when it earns it.

Each turn picks a model in this order: a thread override, the channel’s default, the heavy-model heuristic, then the workspace default. It ships on z-ai/glm-5.3-flash and speaks the OpenAI-compatible API, so any endpoint that does — OpenRouter, a vendor API, or your own host — works.

The heavy model is routed to automatically for asks that look like code or multi-step work, for threads past 25 messages or 20,000 characters, and for threads that have already made eight tool calls. A channel can also just choose it as its default. Images go to a vision model when one is configured.

Every completion’s tokens and cost are stored, so !usage and the console show measured numbers. A workspace monthly budget pauses the bot when the month’s spend passes it; a per-channel budget does the same for one channel; a per-user rate limit caps requests per hour. When a limit trips, an alert is posted once an hour to the channel you nominate.

Commands

Bang commands, handled before the model sees anything.

Cheap, deterministic, and free: none of these spends a token or waits on a completion.

!help
List the commands.
!whoami
Where it is running — platform, OS, host, uptime, build — and what it is: identity, model, storage, timezone.
!restart
Forget this thread's context and start fresh.
!stop
Stop the turn running in this thread right now, and any fix job in it.
!model !model heavy
Override the model for this thread, or put it back to the channel default.
!memory !forget
Show what it remembers here; delete the ones that match.
!routines !routine off
List this channel's routines; disable one.
!jobs !job cancel
List this channel's fix jobs; cancel one.
!usage
This month's spend by channel, against the budget.
!mute !unmute
Stop or resume replies in this thread.

The interesting part is what it can reach.

Connections are how it gets to GitHub, ClickUp, Sentry or your own API — without the model ever holding the credential.