Deploy a Chat Bridge#
How to let your team ask the OSPREY agent questions from a Nextcloud Talk chat room and get answers — including plots and files — back in the same room.
What You’ll Learn
What the Nextcloud Talk bridge does, and what it deliberately does not do
How to create the bot account the bridge speaks as
How to enable the bridge in a build profile and bring it up
Which questions the bridge answers, and who is allowed to ask
Prerequisites: A Nextcloud instance with the Talk app, permission to
create a user account on it, and a project whose profile has a dispatch:
block (see Event Dispatch). Docker or Podman for the container path.
Overview#
The bridge turns a chat room into a way of talking to the agent. Someone mentions the bot in a Talk room, the bridge hands that question to the event dispatch pipeline, and the answer is posted back as a reply in the room.
It is a poller, not a server: it asks Nextcloud for new messages and waits for them, so it opens no network port of its own and nothing has to be able to reach it. It only makes outbound calls — to Nextcloud and to the dispatcher.
flowchart LR
T[Nextcloud Talk room] -->|message mentioning the bot| B[nextcloud-bridge]
B -->|POST /webhook/trigger| D[Event dispatcher]
D --> W[Dispatch worker]
W -->|answer + any files| B
B -->|reply in the room| T
The bridge is the piece that remembers things. Each question is recorded before it is dispatched, so a restart in the middle of one does not answer it twice or drop it; the recent exchanges in a conversation travel with each new question, so “now plot that over 24 hours” makes sense; and each room’s reading position is saved, so messages posted while the bridge was down are picked up rather than missed.
Enable It in a Profile#
Add a nextcloud_bridge: block to your build profile. The only setting is
which dispatcher trigger the bridge fires — that trigger decides what the agent
is allowed to do with a chat question:
nextcloud_bridge:
trigger: nextcloud-question # default; must exist in your triggers file
env:
required:
- NEXTCLOUD_BASE_URL
- NEXTCLOUD_BOT_ACCOUNT
- NEXTCLOUD_APP_PASSWORD
- NEXTCLOUD_ROOMS
Rooms and credentials are not profile settings. They are runtime values you
supply, because they differ per deployment and the password must never be baked
into a build. Listing them under env.required makes osprey build write
them into the project’s .env (created mode 0600, readable only by you)
for you to fill in.
Two mistakes are caught at build time rather than at runtime: declaring the
bridge without a dispatch: block, and naming a trigger that your triggers
file does not declare. Both fail the build with a message naming the problem,
instead of producing a project that deploys and then fails on every message.
Runtime settings#
Variable |
Meaning |
|---|---|
|
Your Nextcloud instance, with no trailing slash, e.g.
|
|
The Nextcloud user id the bridge signs in as — the account people mention to ask a question. |
|
An app password for that account (not the account’s login password). |
|
Comma-separated Talk room tokens to watch. A room’s token is the last
part of its URL: in |
|
The trigger to fire. Filled in for you from the profile block above. |
|
Shared secret for talking to the dispatcher. |
|
Shared secret for talking to the worker. Also auto-generated. |
Bring It Up#
1. Create the bot account. In Nextcloud, add a regular user for the agent to
speak as — the display name is what your team sees replying, so make it obvious
(for example OSPREY agent). Sign in as that user once, then create an app
password under Settings → Security. An app password can be revoked on its own
without disturbing the account, which is why the bridge uses one.
2. Invite it to the rooms it should serve. The bot only sees rooms it is a member of. Add it to each room you want served, and collect those rooms’ tokens.
3. Fill in ``.env`` with the four values from the table above:
NEXTCLOUD_BASE_URL=https://cloud.example.org
NEXTCLOUD_BOT_ACCOUNT=osprey-agent
NEXTCLOUD_APP_PASSWORD=xxxxx-xxxxx-xxxxx-xxxxx-xxxxx
NEXTCLOUD_ROOMS=a1b2c3d4,e5f6g7h8
4. Bring the stack up. The bridge is registered in deployed_services, so
it starts with everything else:
osprey deploy up # add --dev to bake in a local osprey checkout
Then mention the bot in one of the listed rooms and ask it something. If nothing happens, check the service’s logs first: a missing credential stops the bridge at startup with the missing variable named, rather than letting it run in a broken state.
Important
The bridge keeps what it remembers — which questions it has answered, recent
conversation, and each room’s reading position — in a named volume mounted at
/data. Do not remove that volume. Without it, a restart forgets everything
and the room’s history is either replayed from the beginning or skipped past.