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.
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.
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_historyslack_search list_channels list_pins get_usersearch_docsweb_search fetch_urlcreate_artifactremember recall forgetcreate_routine list_routines delete_routinehttp_request + named packsuse_connectionstart_fix_jobDocuments
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.
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
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.
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.
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!whoami!restart!stop!model !model heavy!memory !forget!routines !routine off!jobs !job cancel!usage!mute !unmuteThe 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.