WardrikChannel

Copy Markdown

Lets people talk to Wardrik's agents from chat apps, such as Slack. It handles rooms, threads, replies and approvals.

Each chat app has its own adapter package, such as WardrikSlack. This package holds what every adapter shares.

Install

Add an adapter. It brings this package in.

def deps do
  [
    {:wardrik_slack, "~> 0.1.0-rc.1"}
  ]
end

To write an adapter of your own, depend on this package directly:

{:wardrik_channel, "~> 0.1.0-rc.1"}

Wire it up

A channel is one chat app Wardrik runs, under a name you choose. Give it a token, and the owner whose agents answer there:

defmodule MyApp.AgentRuntime do
  use Wardrik, otp_app: :my_app
end

config :my_app, MyApp.AgentRuntime,
  channels: [
    slack:
      {WardrikSlack,
       token: System.fetch_env!("SLACK_BOT_TOKEN"),
       signing_secret: System.fetch_env!("SLACK_SIGNING_SECRET"),
       owner: "acme",
       approvers: ["@maria"]}
  ]

The chat app posts to POST /v1/channels/slack/{path}. Serve it with Wardrik.HTTP:

forward "/", Wardrik.HTTP, wardrik: MyApp.AgentRuntime

List the channel in an agent's definition:

scope = MyApp.AgentRuntime.as("acme/@maria", roles: [:owner], resources: ["acme/*"])

Wardrik.Agent.define(scope, "acme/triage",
  model: "anthropic:claude-haiku-4-5",
  description: "Triages incidents.",
  channels: ["slack"]
)

Then invite the bot into a room:

  1. If one agent is offered, it answers in that room from then on. With several, someone picks one.
  2. Mention the bot. The agent answers in a thread under your message.
  3. Reply in the thread. The agent answers again, no mention needed.

Threads

Each thread is its own conversation with the agent, with its own history:

acme/triage/slack.T0123.C024BE91L.1696.1234

Anyone in the workspace may message the owner's agents. They act as themselves, as slack:T0123/U024BE7LH.

Replies are read from the agents' logs. Each room has one process in your cluster, kept in Wardrik's store. A reply delayed by a restart is still posted.

Approvals

When an agent waits on a call, the call and its arguments are posted in the thread. These people may decide it:

  • anyone in approvers, as the chat app names people, or everyone with approvers: :anyone
  • whoever asked for that turn

Anyone else is told who may decide.

Many workspaces

token: adds the channel to the one workspace that token reaches. To add one app to many workspaces, such as one per org, give the channel installations: instead of token::

# Kept in Wardrik: owners in its store, tokens sealed with its :keys
installations: :stored

# Kept by your app, in a module implementing Wardrik.Channel.Installations
installations: {MyApp.ChatInstallations, []}

Your adapter's docs list what else it needs, such as Slack's :client_id.

Rooms in the audit

Binding a room is recorded in Wardrik's audit as wardrik.room.bound. Unbinding it is recorded as wardrik.room.unbound. Both say who did it.