MachineMachine
MachineMachine
MachineGetting startedQuickstartAccounts & access
Your project
AgentsLegacy kortix.tomlManifest referenceModelsAgent permissionsSecrets
Running work
Change requestsRuntime & sandboxSessions
Connect & automate
ComputersConnectorsInkbox: iMessage, SMS, email & callsMCP serverPixio: images, video & audioRemindersSlack & channelsMicrosoft TeamsTriggers
Feature flags
Apps

Develop

CLI
TypeScript SDKFull exampleAuthenticationSign in with KortixSessionsAppsReact hooksSDK reference
Machine as a BackendAPI reference
GitHub
Connect & automate

Microsoft Teams

Connect a Microsoft Teams bot so chats and channels start and continue Kortix sessions.

Microsoft Teams is a channel: an @-mention in a Teams chat or channel starts a session, and the agent replies right there with live progress. It follows the same session, identity, and credential rules as Slack; this page covers what is specific to Teams.

Teams is experimental — enable Microsoft Teams under Settings → Feature flags on the project first.

Connect

Two ways, both from the project's Connectors → Channels page:

  • One click (managed). A Teams tenant admin clicks Add to Teams, signs in, and consents. Kortix publishes the app to your org's Teams catalog automatically — there is nothing to build or paste. The row then offers Add to Teams (a deep link into the Teams client) so anyone can add the bot to a chat or channel. When Machine ships a newer version of the app, see Update the app.

  • Bring your own bot. Click Use your own Microsoft Teams app for a three-step wizard: register an Azure Bot, connect it to Kortix with its app id, client secret and tenant id, then download the generated app package and upload it to Teams. Use this on self-hosted deployments or when you run your own registration.

    The order matters. Kortix builds the manifest from your app id, so it can only generate the package after step 2 — the wizard shows you the messaging endpoint to paste into Azure before it asks for anything else.

The CLI mirrors the dashboard:

bash
kortix channels connect --platform teams      # prints the admin-consent URL
kortix channels status --platform teams        # tenant, catalog, publish state, app version
kortix channels disconnect --platform teams

Update the app

Machine adds permissions to its Teams app over time. App version 1.1.0 added ChannelMessage.Read.Group, which the agent needs to read a channel thread. Version 1.3.0 added ChatMessage.Read.Chat, so a group-chat reply continues a session without a mention. A team still on 1.0.0 refuses every thread read, and the refusal the agent receives names who fixes it.

Two people update the app, in this order:

  1. A Teams admin publishes the update. When your org catalog has an older version, the Channels page shows Update the Machine app in Teams, and the Teams row's button reads Publish app update. The admin clicks it and signs in with Microsoft. kortix channels status --platform teams prints both versions, and kortix channels connect --platform teams prints the sign-in link.
  2. A team owner updates the app in each team where Teams offers it. In Teams, open the team, then ⋯ → Manage team → Apps, select Update on the Machine app, and accept it. Teams installs an update on its own unless it adds a permission or a message action; those wait for a team owner.

Machine records the app version at each publish. An install published before Machine recorded versions shows the notice until its next publish.

Chats, channels, and mentions

  • Personal chat: every message reaches the bot.
  • Team channel / group chat: a new post needs an @-mention. After that, a reply in a conversation the bot already owns continues the session without one, the way a Slack thread does. That needs the app's ChannelMessage.Read.Group (channels) and ChatMessage.Read.Chat (group chats) permissions, which the tenant admin consents to when the app is added. If the app was added before these were requested, a team owner updates it: see Update the app.

Each chat or channel conversation is its own session. The first message creates it; later messages continue it, even after the sandbox stops and resumes. A tenant connected to more than one project shows a project picker on the first unrouted message, and remembers the choice. In a channel only a message that mentions the bot gets the picker, and a command about the project, such as /models, asks which project first.

In a channel, every new post starts its own session. A personal or group chat is one conversation for its whole life, so it keeps one session until you send /new. Put a message after it (/new summarize today's deploys) to start the new session with that message. The previous session stays in Kortix, with its full history, and the confirmation links to it.

Conversation names

Teams sends ids, such as 19:…@thread.tacv2;messageid=…. The Channels page and kortix channels bindings show the names people read in Teams:

ConversationNameUnder the name
A channel postTeam › ChannelThe title of its session, which tells two posts in one channel apart
A group chatThe chat's titleGroup chat
A personal chatThe personPersonal chat

A channel message carries the team's id but not its name, so Machine reads the team and channel names from Teams and stores them. A post in a team's General channel is named the next time the Channels page lists it. A post in another channel is named by its next message. Until then it reads Channel thread.

Who may join a session

Each conversation has a join policy, set with /policy in Teams or on the Channels page, where N channels on the Teams row lists every conversation:

  • open (default) — any linked project member may join a session started here.
  • approval — the session owner gets an Approve / Deny card for each new person.
  • owner — only the person who started the session.

Under approval and owner, the session is not visible to the whole project in Machine either: only to its owner, the people approved into it, and account admins who oversee sessions. A decision on a review or approval card resumes the agent under any policy.

Identity linking

The sender links their Kortix account once with /login; the agent then runs as them, with their own credentials, secrets, and connected apps. An unlinked sender, or one without access to the project, gets a card to connect or request access instead of a session.

The sign-in link appears only where you alone can see it: in your one-to-one chat with the bot, or, in a channel or group chat, in a reply marked Only you can see this message. The link connects the person it was issued for to whoever opens it, so it never appears where others can see it. If Teams refuses that private reply, the bot sends the link to your private chat with it and says so in the conversation. Teams allows that only when you have added the app for yourself; otherwise the card asks you to open a private chat with the bot and send /login there. A message you sent in the channel while unlinked runs once you connect, if you do so within 10 minutes. When you finish connecting in the browser, your private chat with the bot confirms which Machine account you are linked as.

A sign-in link works once and expires after 10 minutes. A Teams account that is connected to one Machine account cannot be connected to another: send /logout first. If your organization requires two-factor authentication, Machine asks for your second factor before it connects you, and the chat runs on the factor you connected with. A link made without it asks you to connect again.

When someone without access asks for it, every account owner and admin gets the request in Machine. Those who linked Teams also get it in their private chat with the bot, with a Review in Machine button.

Private replies

In a channel or group chat, what the bot says to one person is visible only to that person, marked Only you can see this message, as Slack's ephemeral messages are:

  • the replies to your commands;
  • the card to connect your account or to request access;
  • why your message did not run: the join policy, or an agent you may not use;
  • under approval, the owner's Approve / Deny card, and the decision to the person who asked.

The Working on it… card that everyone sees appears only when your message may run. Teams deletes a private reply after 24 hours. If Teams refuses a private reply, the bot posts the card for the whole conversation instead. The sign-in link is the exception: it then goes to your private chat with the bot, never to the conversation.

Roles and permissions

A chat carries no Machine credential of its own, so every action runs as the linked Machine account of the person who took it, with that account's project role. Account owners and admins count as project managers.

ActionWho may do it
Send a message the agent answersA linked account with access to the project, within the conversation's join policy
Stop a runThe person who sent the message being answered, or anyone approved into that session, who can still use the project
/new in a group chatA linked project member; under approval or owner, someone approved into the current session
Change the project, agent, model or policyA project manager; in a personal chat with the bot, any project member
Approve or deny a reviewA project manager
Approve or deny a connector callA project manager, or the person who started the session
Approve someone into an approval sessionThe session owner
Request accessAnyone linked; each account owner and admin is notified once

A person scoped out of an agent cannot start a session on it from Teams, as in Machine.

Commands

Type these in a chat with the bot (in a channel, @-mention it first):

CommandWhat it does
/helpList the commands
/login, /logout, /whoamiLink, unlink, or show your Kortix account
/statusThe project, agent, model, session policy and run here, with buttons to change the model, agent or project
/sessionsYour five most recent sessions started from Teams, each with an Open button
/stopStop the run in progress here
/new [message]Start a new session in this chat (personal and group chats)
/models, /model <ref>Pick the model for this conversation — see Models and keys
/agents, /agent <name>Pick the agent for this conversation
/projects, /use <name>List connected projects, or point this one at another (not on a project's own bot)
/policy [open|approval|owner]Who may join sessions started here
/unbindDisconnect this conversation from its project; the next message picks one again
/homeThe organization's projects and what to try

On any message, ⋯ → Open in Machine opens the session that conversation belongs to. When you add the app for yourself, your private chat with the bot starts with the same overview as /home.

Models and keys

/models lists every model you can run here, as the web picker does: Machine models, and models you reach through a provider API key or a ChatGPT subscription. Each one says how it is paid for. A long list is a searchable dropdown. Tap a model, or type /model <id>; /model default goes back to the project default.

Which keys count depends on the chat:

  • A personal chat with the bot — your own keys and ChatGPT subscription, plus keys shared with the project. Its sessions are private to you.
  • A group chat or channel — only keys shared with the whole project. The chat is shared, and a personal key there would let everyone in it spend one person's subscription. Pick such a model in a personal chat instead.

A model that runs on keys uses every key you may use for its provider, and they rotate on rate limits. The choice applies to the next message; the chat keeps its session. Changing the model of a running session needs a linked account, and under the owner or approval policy only the session's owner can change it. A personal chat whose session started before sessions there became private still shares that session with the project: /model says so, and /new starts a private one. See Provider keys and member access.

While the agent works

The agent answers in one card: its steps while it works, then the reply. A long reply that does not fit in one Teams message is cut at a line, marked as cut, and links to the full session in Kortix.

A link you are meant to open is a button, not a word in a sentence: a link to connect an app (Connect Gmail), and any link the agent puts on a line of its own. Other links, code, and tables render as they do in Machine.

Send another message while it works and it waits for the current run, then gets its own card. A run can take as long as it needs: a card is closed as dead only when the runtime reports that the run has ended, not because a long step posted nothing for a while.

Stopping a run

While the agent works, its live card carries a Stop button. /stop does the same thing after the card has scrolled out of reach. Either ends the run at the runtime, not just on the card — a run that is left open swallows the next message in the conversation instead of answering it.

The person who sent the message being answered can stop it, as can anyone approved into that session, while they can still use the project. A bystander in the channel cannot, and neither can someone approved into an earlier session of the chat.

Files

The agent sends files with teams send --file, and Kortix picks the delivery for the conversation:

  • An image is shown inline — in a personal chat, a group chat, or a channel. If it is too large for Teams to carry inline, a personal chat falls back to a consent card (accept, and it lands in your OneDrive) and a channel falls back to the team's files. A group chat cannot receive file transfers, so an oversized image there comes back to the agent as "send a smaller one".
  • Any other file arrives as a consent card in a personal chat, or as a SharePoint link when it is shared to a team.

Inbound files and pasted images are available to the agent to download and work with — including images pasted into a channel or a group chat, which Teams delivers inside the message body rather than as an attachment.

Paste a screenshot and ask about it and the turn runs on a model that can read images, even when the conversation's own model is text-only — the session's model pick is left alone. A model the session can no longer run — a key that was revoked, a ChatGPT subscription the chat cannot use — is replaced for that message the same way, instead of failing it.

Questions and forms

The agent asks with controls, not prose — the same shape as a question in the Kortix app:

  • One question, up to six options — a button per option. One tap answers.
  • Several questions, a pick-several question, or a longer list — one form: each question with its options listed, a box for an answer of your own, and a Send answers button.
  • A date, a time, a number, or an on/off choice — a form with the matching input.

Your answer reaches the agent as your next message, labelled with the question it answers, and the session continues from there. You can always ignore the card and type your answer instead.

Approvals

When an agent needs a human decision before it proceeds — a risky step, a change it wants signed off — it files a review item. If the session was started from this conversation, the decision lands here as a card: the title, a summary, a risk level, and Approve, Request changes and Deny, plus a link into Kortix.

The card carries an optional feedback box. Whatever you type is stored with the decision and passed to the agent with it, so "Request changes" does not cost a second round trip to ask what you meant. It is optional by design — a plain Approve should not need typing.

Anyone in the conversation sees the card, but acting on it needs a linked Machine account that manages the project. The decision resumes the agent whatever the conversation's join policy is.

Posting on its own

Besides replying where it was asked, the agent can post into any chat or channel the bot is already in for this project — a nightly summary, an alert, a hand-off. It cannot reach a conversation it was never added to.

When a session will not start

Kortix says what is wrong instead of asking you to try again, because most start failures never clear on a retry: a sandbox template that no longer exists, an account that is not linked, a project you cannot reach, or a workspace out of credits. Each one names the fix and the command that applies it.

If the agent set for the conversation has been deleted or renamed, the failure arrives as a picker: choose a live agent, then send your message again. The list only offers agents you have access to.

Reading a channel

In a channel the bot only receives messages that mention it, so the discussion it was asked about is not in its session. When it needs that context, the agent reads the thread it was mentioned in, or the channel's recent posts, through the ChannelMessage.Read.Group permission the app requests when it is added to a team. A team that added the app before that permission was requested must update it: see Update the app. In a personal chat every message already reaches the session, so there is nothing earlier to read.

Every project connected to the same Microsoft 365 tenant uses the same app, so Machine keeps each read inside the project's own conversations. In a channel, every new post is its own conversation:

ReadAllowed when
A thread (teams thread)The thread is a conversation of this project, or of no project and the channel is readable
A channel's recent posts (teams history)This project has a conversation in the channel. Posts that start another project's conversation are left out
A channel no project has a conversation inNo other project is connected to the tenant

A refused read answers 403 with the reason conversation_not_in_project and a message that names the channel or thread. To read a channel of the first kind in a tenant with several projects, mention the bot in it and pick this project.

get_channel and list_channels answer for standard channels. A private or shared channel appears only when the agent may read it by the rules above. get_team, list_members, get_user and list_teams read the tenant directory and are not limited.

Limits

Teams bots cannot add message reactions or search messages — those Slack affordances have no Teams equivalent. The agent can read a channel only in a team the app was added to, and only by the rules in Reading a channel.

PreviousSlack & channelsNextTriggers

On this page

ConnectUpdate the appChats, channels, and mentionsConversation namesWho may join a sessionIdentity linkingPrivate repliesRoles and permissionsCommandsModels and keysWhile the agent worksStopping a runFilesQuestions and formsApprovalsPosting on its ownWhen a session will not startReading a channelLimits