Internal support actor
In seat mode, an actor in the chat can only use the workflows your app exposes to end users. That is right for customers, and useless for an assistant that should answer your own team: "what failed in the nightly run?", "is that ticket still open?", "did the release go out?".
Internal mode lets one attached actor reply as an ordinary organization session, with the skills and MCP servers its own agent config declares. It is a per-attachment switch with strict gates.
When you can use it
buzz.actor.set-reply-principal refuses with org_principal_not_allowlisted, contact Orkestia support.All of these must hold, and they are checked again on every message:
- Your organization is enabled for internal mode.
- A person who is an organization admin or owner turns it on, signed in as themselves. API keys, the system, agents and end users are refused.
- The people who may wake the actor are listed. Between 1 and 50 end users of the space's app, each
activeorinvited. - The message's author is on that list.
- Every active person in the space is on that list. Actors do not count. If anyone else joins the space, the actor goes silent until they are removed or listed.
When a gate fails, the actor posts nothing. A polite refusal would tell someone outside the list that an internal assistant sits in the chat. The inbound ledger records why (author_not_allowed, space_has_external_members, org_principal_not_allowlisted).
Turn it on
For an actor that is already attached in seat mode:
start_workflow("buzz.actor.set-reply-principal", {
"space_uuid": "<space uuid>",
"attachment_uuid": "<from data.buzz.attachment.list>",
"reply_principal": "organization",
"allowed_author_end_user_uuids": ["<end user uuid>", "<end user uuid>"]
})
For a new actor, pass reply_principal: "organization" and allowed_author_end_user_uuids to buzz.actor.attach directly. An actor attached this way does not need to declare that it acts as the app.
To go back, set reply_principal to "seat". The actor then needs its act-as declaration again to answer.
What changes in a reply
| Seat mode | Internal mode | |
|---|---|---|
| Runs as | The actor's end-user seat in the app | An organization session of the actor |
| Tools | The app's end-user workflows only | The skills and MCP servers in the actor's own config |
| Platform default tools | Not part of a seat session | Off, forced by the chat whatever the config says |
| Who can wake it | Any member of the space | Only listed people, and only while everyone in the space is listed |
Everything else stays the same: the reply ceiling, duplicate protection, signature checks, the refusal to answer actors, and the actor's end-user seat requirement.
Build a good internal assistant
- Keep the tools narrow. Prefer read tools: actor state, recent failed sessions, ticket search and get, pull request status, the clock. Add a few narrow writes, such as opening a ticket or adding a comment, only when people ask for them.
- Turn memory off. An organization session would otherwise share one memory across everyone who talks to it. Set memory off on the agent config.
- Keep the budget small and the step limit low. A support answer needs a handful of tool calls.
- Tell it to treat tool results as data. Ticket, pull request and session text can contain instructions; the actor must never follow them.
- Put it in a space only your team uses. The "everyone is listed" gate is what keeps organization data out of the wrong conversation.
Audit
- The mode change is recorded on the space with who set it and when.
- Every message that reaches the actor is a ledger row (
data.buzz.inbound.list) with its outcome. - Every reply's actor run is attributed to the chat, with the reply mode and the person who asked, and its session is linked from it, so any answer can be traced back to the question.
Ask your AI assistant
Show me which actors in my chat space reply as the organization and which reply as their seat. Use data.buzz.attachment.list and data.buzz.space.get.
Switch the actor "<actor name>" in my internal chat space to internal mode for these people: <names>. Find their end user uuids with identity.end-user.query and the attachment with data.buzz.attachment.list, then show me the buzz.actor.set-reply-principal call. I will start it myself.
Why did my internal support actor not answer? Read data.buzz.inbound.list for the space and explain the latest reason codes.
For AI agents
| Rule | Detail |
|---|---|
| You cannot switch it | buzz.actor.set-reply-principal refuses agents and API keys. Prepare the call for an org admin or owner |
| Silent by design | No reply plus author_not_allowed or space_has_external_members in the ledger is the gate working, not a bug |
| Enablement | org_principal_not_allowlisted needs Orkestia support. Nothing in the organization can change it |
| Data handling | Answers can carry organization data. Never suggest adding people outside the organization to an internal space |
Actors in chat
Put a Staff actor into a chat space. Seat binding, triggers, the reply ceiling, DGI responders, progress lines, the tool trace, quick replies, handoff to a person, several actors in one conversation, and messages an actor starts from outside the chat
API and console
Every chat workflow you can call from the API, the console or an assistant, who may call it, the end-user entry points, and the console Chat tab
