Quick start
How Ankole is deployed
A private Ankole deployment instance has one control plane and one or more Agent Computer Workers. The control plane is the management platform. A Worker runs Agent tasks and acts as the Agent’s work computer.
One Worker can serve several Agents. In finance or another environment that needs strict isolation, give each Agent a dedicated Worker. A work computer can be shared by several interns or assigned to one colleague.
Each instance also needs PostgreSQL and persistent disk storage. A single-host deployment can use a local or virtual disk. A Kubernetes deployment needs NFS or another shared volume that supports ReadWriteMany.
Terms used in this guide
This page defines the terms used in Ankole user documentation and interfaces. The names in parentheses match third-party platforms, configuration fields, and APIs. Later sections use the short form.
| Canonical term | Meaning | Short form |
|---|---|---|
| Private deployment instance | One complete Ankole system that an enterprise deploys and manages | Instance |
| Principal | A person, Agent, or system service that can have an identity and permissions in Ankole | Principal |
| Identity Provider (IdP) | An external identity source that provides Console SSO and synchronizes employees, contacts, and organization structure | IdP |
| Chat platform | An external conversation platform such as Slack, Teams, Lark/Feishu, or DingTalk | Platform |
| Channel Provider | One chat application or bot configuration that receives messages and sends Agent replies | Channel Provider |
| Signal Routing Rule (Signal Binding) | The rule that sends messages or events from a signal source to an Agent | Routing rule |
| LLM Provider | A configuration that stores a model service endpoint, credentials, and available models | LLM Provider |
Background Agent Jobs profile (internal key: coding) |
Selects the AIGateway provider and model for Background Agent Jobs; normal conversations do not select it by code volume | Background Agent Jobs |
Let an Agent complete the setup
You can send this prompt to Codex, Claude Code, or another Agent that can operate a terminal:
Use https://ankole.agentbull.com/en-US/docs/quickstart/ to help me deploy and configure a private Ankole deployment instance. First, inspect my environment and recommend Docker Compose, Kubernetes, or installing from source. Then help me set up the Identity Provider (IdP), LLM Provider, Agent, Channel Provider, and Signal Routing Rule (Signal Binding). If I did not specify an IdP and IM platform, ask which identity source and chat platform I want to use. Do not choose them for me. Do not expose secrets in chat or command output. You are finished only when I receive a real Agent reply in my selected IM.
1. Deploy Ankole
Use Docker Compose for one host or Kubernetes for an enterprise deployment. Install from source for development and debugging.
The best starting point for most teams. One Linux, macOS, or Windows host with Docker runs PostgreSQL, the control plane, one Agent Computer Worker, and Caddy HTTPS.
Before you start
- A Linux, macOS, or Windows host that can run Linux amd64 or arm64 containers
- Docker Engine with the Compose plugin, or Docker Desktop
- Persistent disk, a DNS name, and ports 80 and 443
Basic setup
Install with Docker Compose
Keep provider API keys out of this deployment file. You will add them in the Console after sign-in.
- 01
Get the deployment package
bashgit clone https://github.com/AgentBull/ankole.git cd ankole/tools/deploy/docker-compose cp .env.example .env chmod 600 .env - 02
Generate three independent secrets
Copy and run this command. Then paste its complete output into .env.
bashprintf '%s\n' \ '# PostgreSQL database password' \ "POSTGRES_PASSWORD=$(openssl rand -hex 32)" \ '' \ '# ANKOLE master encryption key' \ "ANKOLE_SECRET_BASE=$(openssl rand -hex 32)" \ '' \ '# Authentication key shared by the ANKOLE control plane and Agent Workers' \ "ANKOLE_RUNTIME_FABRIC_WORKER_AUTH_KEY=$(openssl rand -hex 32)" - 03
Set the public host
Set ANKOLE_HOST to the DNS name that points to this host. Set ACME_EMAIL to an address that can receive certificate notices.
- ANKOLE_HOST
- ankole.example.com
- The HTTPS host that people and provider callbacks will use.
- ACME_EMAIL
- ops@example.com
- Contact address for Caddy certificate management.
- 04
Start and verify the stack
Compose waits for PostgreSQL, runs migrations, stores the Worker key, and then starts the control plane, Worker, and Caddy.
bashdocker compose pull docker compose up -d docker compose ps - 05
Open the first setup
Open https://<ANKOLE_HOST>/setup and enter the activation code.
bashdocker compose logs control-plane | grep "SETUP ACTIVATION CODE"
2. Set up the identity provider first
Ankole is designed for private deployment inside an enterprise. Each enterprise operates one instance. Inside that instance, Agents, employees, and system services are represented as Principals, and the authorization module manages their permissions.
Like Hermes Agent and OpenClaw, Ankole connects to chat channels. It also connects to the enterprise identity source so it can synchronize employees, directory contacts, and the organization structure. Configure an Identity Provider (IdP) before you configure the chat channel.
| Setting | What it controls | Configure it where |
|---|---|---|
| Identity Provider (IdP) | Console SSO and the employees, contacts, organization structure, and permission groups synchronized from the enterprise directory | /setup first, then Console → Identity Providers |
| Channel Provider | The IM app or bot that receives messages and sends Agent replies | Console → Signal Routing |
The identity source and chat channel can use different platforms. Employees can sign in through Google Workspace and talk to the Agent in Slack. Entra ID can supply identity while Lark, Slack, DingTalk, or Teams carries the conversation.
Complete the setup for your IdP
Select the identity source that your enterprise uses. Each tab starts in the provider console and ends with the first sign-in and directory sync.
If you enable the adapter for the first time, restart the control plane after the first sign-in. This restart starts the plugin background work, such as directory connections and Graph subscriptions.
Use one Slack app for Console sign-in and for workspace member and user-group sync. The default setup needs an OAuth client, a Bot Token, and an App Token.
Before you start
- A workspace administrator who can create and install a Slack app
- A public HTTPS address for Ankole
- A workspace member account for the first sign-in
Basic setup
Set up the Slack IdP
- 01
Copy the callback URL from Ankole
Open https://<ANKOLE_HOST>/setup and enter the activation code. Select Slack Adapter on the plugin page, save the selection, and then select Slack.
Keep the provider ID as slack-main. Copy the login callback URL shown on the page. Do not type or change this URL by hand.
- 02
Create the Slack app
Open Slack API Your Apps and select Create New App → From scratch. Enter an app name and select the workspace that holds your employees.
Open Basic Information → App Credentials. Copy the Client ID and Client Secret.
- 03
Register the login callback
Open OAuth & Permissions → Redirect URLs. Select Add New Redirect URL, paste the complete URL from Ankole, and save it.
Ankole requests the openid, profile, and email sign-in scopes by default. Do not replace them with chat bot scopes.
- 04
Grant directory access and get the Bot Token
On OAuth & Permissions, add the four scopes below under Bot Token Scopes. Then select Install to Workspace and approve the installation.
users:readRead member profiles
users:read.emailRead member email addresses
usergroups:readRead user groups and their members
team:readRead basic workspace information
Copy the Bot User OAuth Token after installation. It must start with xoxb-. Reinstall the app after each scope change.
- 05
Get the App Token and enable Socket Mode
Open Basic Information → App-Level Tokens. Select Generate Token and Scopes, add the scope below, and copy the generated xapp- token. Then open Socket Mode and turn on Enable Socket Mode.
connections:writeLet the App Token open a Socket Mode connection
- 06
Subscribe to directory events
Open Event Subscriptions and enable events. Under Subscribe to bot events, add each of the five events below.
team_joinA member joins the workspace
user_changeA member profile changes
subteam_createdA user group is created
subteam_updatedA user group changes
subteam_members_changedA user-group membership changes
- 07
Enter the Slack values in Ankole
Keep Enable OIDC, Sync directory, and Realtime directory sync on. Select Save and sign in with OIDC, and then complete the Slack authorization.
- Client ID: the Client ID from Basic Information
- Client Secret: the Client Secret on the same page
- Workspace ID: the T… part after /client/ in the Slack web URL; it limits sign-in and directory sync to this workspace
- Bot Token: the xoxb- token
- App Token: the xapp- token
- 08
Verify sign-in and the first sync
After Slack returns to Ankole, this user becomes the first root administrator. Open Console → Identity Providers, select slack-main, and select Run full sync.
When the sync finishes, check Console → Principals and Principal groups for the workspace members and Slack user groups.
3. Add an LLM Provider and create an Agent
An Agent model profile stores a model reference, so add the LLM Provider first. Sign in to the Console. Open Providers → New provider, choose the provider kind, give it a stable Provider ID, enter the endpoint and credential fields, and save.
Provider credentials stay encrypted in the control plane. Do not put them in deployment environment files or Agent files.
Open Agents → New Agent. Give the Agent a stable UID, a clear display name, and a mission that says what it owns and what counts as an acceptable result.
Then configure its model profiles:
| Profile | First-run use |
|---|---|
primary |
Main reasoning model |
light |
Short and frequent work |
heavy |
Hard synthesis |
All three are required before the Agent can run. For the first conversation, you can bind the same known-good provider and model to all three. Split them only after the end-to-end path works.
4. Connect a chat channel and create its signal routing rule
Enable the chat platform’s Control Plane Plugin in the Console, and then create the bot or application on that platform. Use separate apps for the IdP and chat roles, even when both use the same platform. This separation keeps sign-in and directory permissions away from bot permissions. It also separates credential rotation and app releases.
One chat app usually represents one bot identity. If several Agents need different bot names, avatars, or permissions, create several apps on that platform. After you prepare an app, create its routing rule in the Console and connect it to the intended Agent.
Slack uses Socket Mode. Ankole opens an outbound WebSocket, so the chat path does not need a public Slack webhook.
Before you start
- Permission to create and install a Slack app
- A test channel or direct message
Basic setup
Prepare a Slack app
- 01
Create the app and enable Socket Mode
Create a Slack app from scratch. Under Basic Information, create an App-Level Token, add the scope below, and then enable Socket Mode.
connections:writeLet the App Token open a Socket Mode connection
- 02
Subscribe to the first message events
Open Event Subscriptions → Subscribe to bot events. Add each event below.
app_mentionReceive channel @-mentions
message.imReceive direct messages
- 03
Grant scopes and install the app
Under OAuth & Permissions → Bot Token Scopes, add each scope that matches the conversations you will use. The first two are required.
app_mentions:readRead channel messages that mention the bot
chat:writeSend bot replies
channels:historyRead public channel messages
groups:historyAdd when the bot must read private channels
im:historyAdd when the bot must read direct messages
Install the app to the workspace after each scope change.
- 04
Collect the Console fields
- botToken
- xoxb-…
- Bot User OAuth Token. The xoxb- prefix is required.
- appToken
- xapp-…
- App-Level Token for Socket Mode. The xapp- prefix is required.
Complete the connection in the Console
The current release uses a direct connection. One routing rule connects one Channel Provider to one Agent. It records the adapter, app credentials, target Agent, group-message behavior, and memory behavior. Create a separate rule for each bot.
In the Console, open Signal Routing → New routing rule and set:
| Field | What to choose |
|---|---|
| Target Agent | The Agent you created in step 3 |
| Adapter | Slack, Teams, Lark/Feishu, or DingTalk |
| Rule name | A stable name such as slack-main or lark-main |
| Group message mode | Start with addressed_only |
| Confidential memory | Leave off for the first test |
| Channel settings | Paste the credentials and values from the channel tab |
Save the rule. The list must show it as enabled. If the form rejects a credential, fix that error before testing the IM; the adapter has not opened its connection yet.
5. Talk to the Agent in the IM
Add the bot to a test conversation. For Slack, Teams, Lark/Feishu, or DingTalk group chat, start with an explicit @-mention:
@Ankole What can you do, and which team are you serving?
After the first real model reply, tune the Agent mission, models, and group-chat policy for the team.
If the Agent does not reply
Check one boundary at a time, in this order:
- The latest provider app version is published and available to the test user.
- The bot is installed in the channel, team, or conversation.
- The required message event and scopes are active.
- The routing rule is enabled and points to the intended Agent.
- The Agent has
primary,light, andheavymodel profiles. - The LLM Provider credential and model selector are valid.
- At least one Worker is ready.
For Compose, inspect docker compose logs -f control-plane worker. For Kubernetes, inspect the control-plane and Worker pod logs. Read only the relevant error; do not print environment variables or secrets.
Once the reply arrives, continue with Agents, Signal routing rules, or Background Agent Jobs.