Nextcloud Talk#
How to let your team ask the Osprey agent questions from a Nextcloud Talk room, and get answers, plots, and files back in the same room.
Before you start
A project whose build profile has a
dispatch:block — see Event Dispatch.Docker or Podman, for the container path.
A Nextcloud instance with the Talk app, and permission to create a user account on it.
Overview#
The bridge turns a Talk room into a way of talking to the agent. Someone mentions the bot in the 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, making only outbound calls.
Like every bridge, it remembers each question and conversation. What is particular to Talk is that each room’s reading position is saved too, 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 documents them in
.env.example; fill the values into the profile’s .env, which is
where a secret survives a rebuild. The build derives the project’s .env
from it (created mode 0600, readable only by you).
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. |
Optional settings you can usually leave alone
Variable |
Meaning |
|---|---|
|
Where the dispatcher and worker are. Filled in for you when they run in the same stack; when they run elsewhere you must set them, and the bridge refuses to start without them. |
|
How long the worker may spend on one run. Comes from your project configuration, so raising it raises it for both halves at once. |
|
How long the bridge waits for an answer before giving up on it. Defaults to 30 seconds more than the worker’s own limit, and may never be less than that limit — the bridge refuses to start if it is. |
|
Seconds between checks on an answer in progress (default 2). |
|
Seconds between sweeps of the queue of questions that could not be handed off yet (default 60). |
|
How long a failed hand-off is held before it is retried, so a brief outage has time to clear (default 20 minutes). |
|
Age at which a question that still cannot be handed off is abandoned (default 48 hours). |
|
Hard ceiling on how long anything may sit in that queue, whatever its state (default 7 days). |
|
Set to |
|
Where the bridge keeps what it remembers. Both default to files under
|
|
Timezone, taken from your project configuration so timestamps match the rest of the stack. |
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 the environment file. Set the four values from the table above in
the profile’s .env (the build derives the project’s .env from it):
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 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.