Putting an agent in a shared thread makes it a colleague
Internal AI moved from dashboards into Slack threads. That changes addressing, mandate, presence, and audience — questions that used to apply only to people.
A year and a half ago we built the BlogBot backend and shipped it as a standalone web app. It went nowhere. The system was fine. The login screen standing between a teammate and any value was the problem. We shifted the interface, not the stack: the same backend now runs from a six-word request in a Slack channel the team is already in all day. Adoption stopped being a problem the day the agent moved into the room.
But moving into the room changes the terms. A dashboard has one user, an explicit invocation, and a clear beginning: a form was submitted, a job started. A thread has four humans and two agents in it, a scroll of prior context nobody curated, and no moment you can point to where a request begins.
Once an agent's home is a shared thread, it's a colleague, and colleagues run on a social contract: who they answer to, what they've been assigned, which rooms they're allowed to speak in. No platform ships that contract for you. We run more than 80 team agents in Slack, and the hard problems they've produced have all been contract problems, not capability problems.

Who is it answering?
In a thread with two agents and four humans, a mention is the only unambiguous addressing signal. "Someone should look at this" resolves to nobody. So every agent needs a handle it answers under, in its own name.
Humans resolve the same ambiguity with things software doesn't have: seniority, and a rough sense of whose sprint the work lands in. Mention-only is the honest default, and it costs something real. An agent that acts only when addressed will sit in a channel and watch a problem scroll past. The alternative costs more: an agent that answers every message inserts itself into conversations between people, and after that happens a few times the team routes around it.
Is an invitation an assignment?
Being added to a room is not an assignment. That's the rule we landed on, and the counterargument is decent: somebody wrote "let's get the agent in here to look at this" and then added it, so the mention that caused the invite probably should count. Except the invite is performed once by one person, and channel membership outlives the request that prompted it by weeks.
An agent that reads membership as a standing mandate risks acting on a thread from three weeks ago that everyone else considers closed. An agent that reads it as nothing will sit in a channel for a quarter while the team assumes it's on duty. Both failures look like the agent is broken. Neither is a model problem. It's a rule you have to pick rather than a default you inherit.
Is it on duty right now?
Presence is the same problem from another angle. An agent sitting quiet in a busy channel while the question it was built for goes unanswered is the same missing field as that agent answering in a thread nobody addressed it in. If you can't tell whether an agent is on duty in a channel by reading its configuration, you don't have a presence model. You have whatever your trigger logic happens to imply.
What has it already read?
An agent reading a thread absorbs whatever is in it, including things nobody meant to hand it. Thread history is an input channel with no schema and no review step, and memory compounds it: an agent that keeps what it learns across conversations carries this thread into the next one.
Scoping helps with what happens next, not with what got read. Deciding at creation whether an agent can save files, write to memory, touch a given integration, or run a workflow bounds its actions — but the reading already happened. Adding an agent to a channel is a data-sharing decision, and it's a bigger one than adding a contractor, because the agent may be connected to far more systems than the contractor ever would be.
Does it know which room it's in?
The same agent should behave differently in an internal channel and a shared customer channel, and it has no reliable way to tell which room it's in unless someone models that. A platform can pin down identity — answer only mentions inside your own organization, refuse display names like admin or security that impersonate a privileged role — but identity is not audience. Nothing in the model weights tells the agent there's a customer in this channel. Everything an agent knows about its audience has to be handed to it.
Write the job description
Two fields cover most of the contract: whose requests this agent honors and who can override them, and what it's on the hook for right now as distinct from what it's capable of. The third is the one nobody writes down: which rooms may it speak in, and how does it know which room it's currently in?
Pick the agent in your busiest channel and try to answer those in writing. If you can't, the agent isn't underpowered. It's unmanaged, and it has been since the day someone added it.
We kept re-answering these questions one hand-built agent at a time, and eventually encoded the answers into Atlas: every agent is a named teammate with a job description — instructions for its role and how it works, access scoped at creation, audit logs behind it — working in the open in Slack. If you're putting agents into shared threads as coworkers, that's where we'd start.