AI labels
For: tenant admins and governance reviewers.
Orchestrator Zero adds an AI label on the supported console, chat and connector surfaces listed below. The label is on by default and says AI agent unless a tenant changes its wording. APIs provide label metadata for clients to display; CLI and SDK response text is not prefixed automatically.
Where the label is
| Where | How it looks |
|---|---|
| Chat channels: openings, answers, questions, approvals and notices in Slack, Discord or any channel plugin | In the message itself: [AI agent] The deploy is green. Slack and Discord show it in the message's text, not only in the app's name. |
What an agent posts to a chat with a plugin's send (oz0_slack.send, oz0_discord.send) | The same prefix, from the call's _meta |
What an agent posts by calling a channel's post function itself (oz0_slack.post, oz0_discord.post), which the agent's manifest lists | The same prefix, from the call's _meta: a label argument the agent passes is not used |
| Issues, comments, pull requests and reviews ai.oz0/github writes for an agent | A small first line: <sub>[AI agent]</sub>, on each line comment of a review too |
| Mail agents send with ai.oz0/email | Details |
| Safe outputs the edge posts to their receiver | "ai_label": "AI agent" in the JSON body: a receiver that shows the request to people shows the label with it |
| The MCP server's answers | _meta["ai.oz0/ai-label"] on each result and task, and a question's elicitation message starts with [AI agent] |
| A2A tasks | Messages already say ROLE_AGENT; the task's, its messages' and its artifact's metadata carry ai.oz0/ai-label |
| The runtime API's jobs | ai_label on the job that GetJob and StartJob answer: the tenant's label for the job's agent, empty when it is off, for an app that shows the agent's words to put it in them |
| The AG-UI route | At the start of the first TEXT_MESSAGE_CONTENT of each of the agent's messages, in the text itself, and in the message start's metadata["oz0/ai-label"]; a question's interrupt message starts with it, and every interrupt's metadata["oz0/ai-label"] names it |
| The chat app example | At the start of each answer's text, and of each question the agent asks, as the AG-UI route sends them; approvals name it beside their words |
| The console | A badge on each answer of a conversation, on a job's Answer tab, and on questions and approvals agents ask |
Mail agents send with ai.oz0/email
A line of its own at the start of the text body, [AI agent], and a paragraph that is the first element of the HTML body.
The edge puts it in, stacks it above the rest of the body and puts the rest in a box that clips what it paints, and refuses HTML that could hide or cover it in a client that reads neither: styles are read as CSS reads them, whatever their spelling (a comment in a property's name, a vendor prefix), and what could paint over the label is refused or bounded (a <dialog>, an inline element's top padding and border, a font's size however it is nested, a line's height)
An app on the AG-UI route gets the label in the agent's text, where it stays whatever the app does with the text. How the app shows its own users that they talk to an AI, and what else it must tell them, is the app maker's to decide.
MCP has no field for who wrote a result, so the label goes in _meta, the place MCP keeps for what it does not name; the result's text stays the agent's, since a calling model reads it and structuredContent must match the agent's output schema. A2A says who wrote a message with its role, and the label adds the tenant's words in metadata.
Word it
oz0 tenant ai-label show
oz0 tenant ai-label set --text '{agent} (AI)' --reason "brand guide 3"
oz0 tenant ai-label set --language sv='{agent} (AI-agent)' --language de='KI-Agent' --reason "Swedish and German readers"
The label is a governance setting: every change takes --reason (and may take --decision-ref), which the audit log keeps.
AI label of tenant default: on, set by user:admin just now
wording {agent} (AI)
reads [agent (AI)] ...
de KI-Agent
sv {agent} (AI-agent)
{agent} is the agent's name, so {agent} (AI) reads [pr-reviewer (AI)] .... A wording is plain text on one line, at most 60 characters, without markup or mentions, and it must say more than {agent}: --text '{agent}' is refused.
A wording should say that an AI wrote the message. One with no word such as AI, KI, IA or bot in it (Support team, say) is kept, but set and show print a warning, Govern › Policy › AI label shows it, and the audit log keeps the change as tenant.ai_label.unmarked too.
The check knows a handful of words in common languages; if your wording says AI in words it does not know, the warning is the only effect.
A wording per language is used where the reader's language is known: in the console, your browser's. Chat posts, comments and API answers use the tenant's wording.
--default goes back to AI agent, and --language sv= removes one language.
Admins of the tenant set the label under Govern › Policy, More, AI label, too; readers see it there. Edges label with a new wording within seconds, and nodes from their next heartbeat.
Turning it off
The label is on unless an admin turns it off, with a reason:
oz0 tenant ai-label set --off --reason 'a test workspace where only bots read'
warning: The AI label is off: people who read this tenant's agents in chat systems, on GitHub, through MCP and A2A and in the web UI are no longer told by the platform that an AI agent wrote what they read. Article 50 of the EU AI Act ...
--off without --reason is refused, and with four eyes on, turning it off waits for another admin. The audit log keeps every change as tenant.ai_label, and turning it off as tenant.ai_label.off, with the reason and the warning the admin was shown; --on turns it on again (tenant.ai_label.on). While it is off, Govern › Policy › AI label says so in a warning. Two admins who change the label at once each get the audit entries of their own change: the setting before a change is read with the tenant's row locked.
The EU AI Act
Article 50 of the EU AI Act (Regulation (EU) 2024/1689) has transparency duties that apply from 2 August 2026: AI systems that interact with people are to tell them they interact with an AI system, unless that is obvious from the context; AI-generated text published to inform the public on matters of public interest is to be disclosed; and the information is to be given clearly, at the latest at the first interaction.
What the label does: it tells the people who read your agents' messages, in the message itself, that an AI agent wrote them, from the first message of a thread on.
What it does not do, and what stays yours:
- It is not legal advice, and turning it on does not by itself settle what Article 50 asks of you. Whether and how Article 50 applies to you, as a provider or a deployer, is for you and your counsel to decide.
- It does not mark generated images, audio or video, and it is not a watermark: text that someone copies out of a message loses the label.
- It labels what goes through the platform's surfaces. What a receiver of a safe output, a plugin that is not one of the verified ones, an MCP or A2A client, or your own code does with an agent's text (and whether it shows
ai_labelor_meta) is up to them. - It labels by where a message comes from, not by who chose its words: a flow step that comments with a fixed template through
ai.oz0/githubis labelled like an agent's comment, and so is a platform notice in a chat thread. - The CLI and the SDKs give you an agent's text as it wrote it:
oz0 run,oz0 job getandoz0 approval listprint answers and questions with no label, and so do the admin and runtime APIs they call. You are the one reading there, and you asked the agent. Where your code passes that text on to other people, labelling it is up to your code. - The three-second acknowledgements a chat plugin's manifest gives (Slack's
On it.) are the platform's own words, not an agent's, and carry no label. - Channels that are neither chat plugins nor ai.oz0/email come later. In mail the label holds where the reader's mail client shows the HTML as written. Where a client reads positioned or clipped styles (as browsers and most mail clients do), nothing in the body paints over the label.
In one that reads neither, the bounds on styles and font sizes keep a line's text near its line, but text whose glyphs or stacked accents reach far above it (in any font) can still paint over the label there. What a client's own style sheet adds beyond the HTML standard's is outside what the edge checks.