Skip to content

Commit 7ce6bb7

Browse files
docs(examples): set up Slack and Discord from the CLI, add GitHub PR mentions, list only non-default tools (#620)
1 parent 66d2f4a commit 7ce6bb7

29 files changed

Lines changed: 1071 additions & 275 deletions

File tree

‎docs/examples/browser-agent.mdx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ description: A long-running agent that signs in to your web apps and works in a
44
icon: "globe"
55
---
66

7-
It signs in to your web apps with credentials stored as Omnara [secrets](/organization/secrets), then works in a real browser: pulling data out of dashboards, filling in forms, or working through a queue overnight. It can run one set job on a schedule or take whatever tasks your team sends it in Slack, with screenshots in its updates. Passwords never pass through the model, and it enters authenticator app codes itself, so it can sign in unattended. It runs on a large machine that's kept, browser and sign-ins included, until you archive the agent, and it asks before anything you haven't allowed it to do on its own.
7+
It signs in to your web apps with credentials stored as Omnara [secrets](/organization/secrets), then works in a real browser: pulling data out of dashboards, filling in forms, or working through a queue overnight. It can run one set job on a schedule or take whatever tasks your team sends it in Slack or Discord, with screenshots in its updates. Passwords never pass through the model, and it enters authenticator app codes itself, so it can sign in unattended. It runs on a large machine that's kept, browser and sign-ins included, until you archive the agent, and it asks before anything you haven't allowed it to do on its own.
88

99
## Build it
1010

11-
Give this prompt to Claude Code, Codex, Cursor, or any other coding agent. It asks about the work, which sites the agent signs in to and how, whether it runs on a schedule, and whether you want it in Slack. Then it builds the agent in your Omnara project and has it sign in to each site once.
11+
Give this prompt to Claude Code, Codex, Cursor, or any other coding agent. It asks about the work, which sites the agent signs in to and how, whether it runs on a schedule, and whether you want it in Slack or Discord. Then it builds the agent in your Omnara project and has it sign in to each site once.
1212

1313
```text
1414
Read https://raw.githubusercontent.com/omnara-ai/omnara/main/examples/browser-agent/SKILL.md and follow it to build my browser agent.

‎docs/examples/mounted-storage.mdx‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,11 @@ machine_sources:
5656
- machine_name: sharepoint-docs # the name from Connect machine
5757
cwd: /mnt/sharepoint
5858
tools:
59+
# Machine tools such as run_command and upload_file are added automatically;
60+
# list one here only to change its permission.
5961
run_command:
6062
permission:
6163
mode: always_allow
62-
write_process: {}
63-
read_process: {}
64-
stop_process: {}
65-
list_processes: {}
66-
list_machines: {}
67-
inspect_machine: {}
6864
ask_question: {}
6965
```
7066

‎docs/examples/overview.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Give one prompt to Claude Code, Codex, Cursor, or any other coding agent, and it
3939
A read-only production investigator for AWS logs, metrics, and infrastructure, plus your code if you connect it
4040
</Card>
4141
<Card title="Coding agent in Slack" icon="code-pull-request" href="/examples/slack-coding-agent">
42-
Mention it in Slack and it fixes the issue in your repository and opens a pull request
42+
Mention it in Slack, Discord, or on a GitHub pull request, and it fixes the issue and opens or updates a pull request
4343
</Card>
4444
</CardGroup>
4545

‎docs/examples/slack-coding-agent.mdx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
---
22
title: Coding agent in Slack
3-
description: Mention it in Slack and it fixes the issue in your repository and opens a pull request
3+
description: Mention it in Slack, Discord, or on a GitHub pull request, and it fixes the issue and opens or updates a pull request
44
icon: "code-pull-request"
55
---
66

7-
Describe a bug, paste an error, or link an issue in Slack, and it works on a fresh clone of your GitHub repository, makes a focused fix, and opens a pull request. Reply in the thread to ask for changes, and it splits larger tasks across copies of itself.
7+
Describe a bug, paste an error, or link an issue in Slack or Discord, or mention it on a GitHub pull request, and it works on a fresh clone of your GitHub repository, makes a focused fix, and opens a pull request. Reply in the thread to ask for changes, and it splits larger tasks across copies of itself.
88

99
## Deploy
1010

‎examples/browser-agent/README.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ A long-running agent that works in a real browser. It signs in to your web
44
apps with credentials you store in Omnara, then does the work there: pulling
55
numbers out of a dashboard, filling in forms, moving records between sites,
66
or working through a queue overnight. It can run one set job on a schedule,
7-
or take whatever tasks your team sends it in Slack.
7+
or take whatever tasks your team sends it in Slack or Discord.
88

99
> Pull last month's invoices over $5,000 from the billing portal into a CSV.\
1010
> Signed in. The invoice list paginates 25 at a time, so I'm filtering by date first. [screenshot]\
@@ -31,7 +31,7 @@ Read https://raw.githubusercontent.com/omnara-ai/omnara/main/examples/browser-ag
3131

3232
Your coding agent follows [SKILL.md](SKILL.md). It first asks about the work,
3333
which sites the agent signs in to and how, when it runs, whether you want it
34-
in Slack, and what it may do without asking. Then it writes the agent from
34+
in Slack or Discord, and what it may do without asking. Then it writes the agent from
3535
your answers, stores the sign-ins, and has the agent sign in to each one while
3636
you watch. SKILL.md is plain steps with the exact `npx omnara` commands if
3737
you'd rather run them yourself.
@@ -71,7 +71,7 @@ on the same site take turns.
7171
| Setting | Default | In this agent |
7272
| --- | --- | --- |
7373
| `machine_memory_mb` | The pool's default size | `8192`, or the pool's maximum, for Chrome and Blaxel's in-memory file system |
74-
| `delete_after_idle_minutes` | The pool's idle-deletion period, which would delete the machine and its sign-ins | `0`: kept until the agent is archived. In Slack every thread gets its own machine, so archive a thread's agent when its work is done, or set a period (at least `5` minutes) to remove idle machines automatically |
74+
| `delete_after_idle_minutes` | The pool's idle-deletion period, which would delete the machine and its sign-ins | `0`: kept until the agent is archived. In Slack or Discord every thread gets its own machine, so archive a thread's agent when its work is done, or set a period (at least `5` minutes) to remove idle machines automatically |
7575
| `sleep_after_ms` | A short idle period on the default pool | `7200000`: sleeps after two hours with no command running, and wakes in under a second with Chrome, memory, and files intact. `0` (never) when a site texts or emails codes |
7676
| `AGENT_BROWSER_IDLE_TIMEOUT_MS` | One hour: agent-browser closes the browser after an hour without commands | `0`: the browser stays open |
7777

‎examples/browser-agent/SKILL.md‎

Lines changed: 105 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: browser-agent
3-
description: Build and deploy a Browser Agent on Omnara, a long-running agent that signs in to web apps with stored credentials and works in a real browser, overnight if needed. Interviews the user about the job, sign-ins, schedule, and Slack first. Use when the user asks to build, deploy, set up, update, or remove a browser agent.
3+
description: Build and deploy a Browser Agent on Omnara, a long-running agent that signs in to web apps with stored credentials and works in a real browser, overnight if needed. Interviews the user about the job, sign-ins, schedule, and Slack or Discord first. Use when the user asks to build, deploy, set up, update, or remove a browser agent.
44
---
55

66
# Build the Browser Agent
@@ -58,9 +58,10 @@ is fine. Don't ask for passwords here; step 4 collects them.
5858
Microsoft).
5959
3. **When it runs.** Whenever someone starts it, or on a schedule such as
6060
every night at a set time? For a schedule, get the time and timezone.
61-
4. **Where they follow it.** Suggest Slack: the team mentions the bot to start
62-
a task, and updates, screenshots, questions, and results arrive in the
63-
thread. The Omnara console always works too. Ask whether they want a
61+
4. **Where they follow it.** Suggest Slack or Discord, whichever the team
62+
uses: the team mentions the bot to start a task, and updates, screenshots,
63+
questions, and results arrive in the thread. The Omnara console always
64+
works too. Ask whether they want a
6465
screenshot with every update (the default), only with questions, or only
6566
with the result.
6667
5. **What it may do on its own.** Overnight no one is around to approve
@@ -240,17 +241,20 @@ usual causes are a sign-in URL that redirects elsewhere (store the URL the
240241
form actually lives on) or a site that blocks headless browsers from
241242
datacenter IPs (see "If a site blocks the agent" in `README.md`).
242243

243-
Keep this agent if the user wants a schedule without Slack; step 9 uses it.
244-
Otherwise archive it in the console once every sign-in works.
244+
Keep this agent if the user wants a schedule without Slack or Discord; step 9
245+
uses it. Otherwise archive it in the console once every sign-in works.
245246

246-
## 8. Connect Slack (if chosen)
247+
## 8. Connect Slack or Discord (if chosen)
247248

248-
If `npx omnara integrations list` already shows an active `slack_thread`
249-
integration for this agent, from an earlier run of this skill, reuse it: skip
250-
to step 4, and if `npx omnara integrations get <integration-id>` doesn't list
251-
the profile under `settings.launcher.profiles`, add it with
252-
`npx omnara integrations profiles <integration-id> --profile-ids <agent-profile-id>`.
253-
The flag replaces the offered profiles, so repeat it for each one already listed.
249+
**Slack.** If `npx omnara integrations list --json` already has an integration
250+
named `browser-agent-slack` from an earlier run of this skill, reuse it whatever
251+
its state, since names are unique in a project. If
252+
`npx omnara integrations get <integration-id> --json` doesn't list this profile
253+
under `settings.launcher.profiles`, add it with
254+
`npx omnara integrations profiles <integration-id> --profile-ids <agent-profile-id>`;
255+
the flag replaces the list, so repeat each profile already there. Then, if its
256+
`state` is `active`, skip to its last step. If it's `disconnected`, setup didn't
257+
finish: skip step 2, and redo step 1 only if the token in `.env` has expired.
254258

255259
1. The user creates an app configuration token at
256260
[api.slack.com/apps](https://api.slack.com/apps) under **Your App
@@ -260,13 +264,13 @@ The flag replaces the offered profiles, so repeat it for each one already listed
260264
starts this agent, and note the `itg_…` ID it returns:
261265

262266
```sh
263-
npx omnara integrations create --name browser-agent \
267+
npx omnara integrations create --name browser-agent-slack \
264268
--integration-kind slack_thread \
265269
--settings '{"launcher":{"profiles":["<agent-profile-id>"]}}' --json
266270
```
267271

268272
The name is permanent and names the agent's Slack tools
269-
(`int__browser-agent__post_message`).
273+
(`int__browser-agent-slack__post_message`).
270274
3. Create the Slack app and connect it:
271275

272276
```sh
@@ -281,6 +285,78 @@ The flag replaces the offered profiles, so repeat it for each one already listed
281285
4. Tell the user to invite the bot to a channel (`/invite @Browser Agent`). A
282286
private channel suits it, since its updates show data from the sites.
283287

288+
**Discord.** The bot answers in a new thread wherever it's mentioned in a
289+
server channel; it doesn't answer direct messages.
290+
291+
If an integration named `browser-agent-discord` already exists, reuse it the
292+
same way: add this profile if it's missing. If it's `active`, skip to step 5;
293+
Omnara can't tell whether steps 5 and 6 were done in Discord, so check them with
294+
the user. If it's `disconnected`, skip step 3 and do the steps that weren't
295+
done, passing the current `setup_revision` from
296+
`npx omnara integrations get <integration-id> --json` in step 4.
297+
298+
1. The user creates an application named "Browser Agent" in the
299+
[Discord Developer Portal](https://discord.com/developers/applications);
300+
ask before choosing a different name, since it's how the team mentions
301+
the bot. They copy the **Application ID** and **Public Key** from
302+
**General Information**. Under **Bot**, they select **Reset Token** to copy
303+
the bot token, turn on **Message Content Intent**, and turn off **Public
304+
Bot** so only they can add it (if Discord refuses, first set
305+
**Installation** → **Install Link** to **None**). Have the user add the
306+
values to `.env`:
307+
308+
```sh
309+
DISCORD_APPLICATION_ID=...
310+
DISCORD_PUBLIC_KEY=...
311+
DISCORD_BOT_TOKEN=...
312+
```
313+
314+
2. Store the bot token and note the `sec_…` ID. If a secret named
315+
`browser-agent-discord-bot-token` already exists
316+
(`npx omnara secrets list --owner-kind project --owner-project-id <project-id> --name browser-agent-discord-bot-token --json`),
317+
reuse its ID; if the user has reset the token since, have them paste the new
318+
one into it on the dashboard's **Secrets** page (the ID stays the same).
319+
Otherwise:
320+
321+
```sh
322+
set -a && . ./.env && set +a
323+
npx omnara secrets create --owner-kind project --owner-project-id <project-id> \
324+
--name browser-agent-discord-bot-token --material-kind generic \
325+
--material-value "$DISCORD_BOT_TOKEN" --json
326+
```
327+
328+
3. Create the integration with this profile in its launcher, and note the
329+
`itg_…` ID and `setup_revision` it returns:
330+
331+
```sh
332+
npx omnara integrations create --name browser-agent-discord \
333+
--integration-kind discord_thread \
334+
--settings '{"launcher":{"profiles":["<agent-profile-id>"]}}' --json
335+
```
336+
337+
The name is permanent and names the agent's Discord tools
338+
(`int__browser-agent-discord__post_message`).
339+
4. Connect the bot. Omnara checks the token and finds the bot's user:
340+
341+
```sh
342+
set -a && . ./.env && set +a
343+
npx omnara integrations configure <integration-id> \
344+
--expected-setup-revision <setup-revision> \
345+
--provider-tenant-id "$DISCORD_APPLICATION_ID" \
346+
--credential-secret-id <secret-id> \
347+
--provider-config "{\"public_key\":\"$DISCORD_PUBLIC_KEY\"}" --json
348+
```
349+
350+
5. Under **General Information**, the user sets **Interactions Endpoint URL**
351+
to `https://app.omnara.com/api/integrations/discord/<application-id>/interactions`
352+
and saves; the buttons on the bot's questions need it. Discord checks the
353+
URL when it's saved, so this has to come after step 4.
354+
6. The user adds the bot to their server by opening this link, which asks
355+
only for the permissions the bot needs:
356+
`https://discord.com/oauth2/authorize?client_id=<application-id>&scope=bot&permissions=309237746752&integration_type=0`.
357+
A private channel suits it, since its updates show data from the sites;
358+
the user adds the bot to it under the channel's **Permissions**.
359+
284360
Each mention in a new thread starts a new agent with its own machine, and
285361
replies in the thread go to the same agent. Kept machines count toward the
286362
pool's machine limit, so tell the user to archive a thread's agent in the
@@ -291,11 +367,11 @@ console when its work is done.
291367
A schedule sends each run's message to one standing agent, so every run uses
292368
the same machine and starts signed in:
293369

294-
- **With Slack:** have the user mention the bot once in the channel where the
295-
results should go, for example "@Browser Agent this thread is for your
296-
nightly runs; reply 'ready' and wait". Get that agent's ID from the
297-
conversation's URL in the console.
298-
- **Without Slack:** use the agent from step 7.
370+
- **With Slack or Discord:** have the user mention the bot once in the
371+
channel where the results should go, for example "@Browser Agent this
372+
thread is for your nightly runs; reply 'ready' and wait". Get that agent's
373+
ID from the conversation's URL in the console.
374+
- **Without either:** use the agent from step 7.
299375

300376
Convert the time and timezone from answer 3 to a five-field cron expression:
301377

@@ -309,13 +385,13 @@ npx omnara crons create --name browser-agent-nightly \
309385
If `npx omnara crons list --name browser-agent-nightly --json` already shows a
310386
trigger, use `npx omnara crons update <cron-trigger-id>` instead. If a run is
311387
still going when the next fires, the message waits in the queue. Don't target
312-
the profile, and don't use the Slack integration's **Add schedule**: both
313-
start a new agent, with a new kept machine, every run.
388+
the profile, and don't use the Slack or Discord integration's **Add
389+
schedule**: both start a new agent, with a new kept machine, every run.
314390

315391
## 10. Wrap up
316392

317-
Summarize what you created: the secrets, the profile, and the Slack app and
318-
schedule if any. Then tell the user:
393+
Summarize what you created: the secrets, the profile, and the Slack or Discord
394+
integration and schedule if any. Then tell the user:
319395

320396
- **Machines are kept** until their agent is archived, sleeping when idle and
321397
waking with the browser intact. Archive agents whose work is done.
@@ -326,8 +402,9 @@ schedule if any. Then tell the user:
326402
- **To rotate a password,** update its secret on the **Secrets** page, then
327403
start a new agent the same way; running machines keep the old value.
328404
- **To remove it,** delete the cron trigger (`npx omnara crons delete <id>`),
329-
delete the Slack integration (`npx omnara integrations delete <integration-id>`),
330-
or, if other agents share it, rerun `npx omnara integrations profiles` with
331-
only their profiles. Then run
332-
`npx omnara profiles delete <agent-profile-id>` and
405+
delete the Slack or Discord integration
406+
(`npx omnara integrations delete <integration-id>`), or, if other agents
407+
share it, rerun `npx omnara integrations profiles` with only their
408+
profiles. Then run `npx omnara profiles delete <agent-profile-id>` and
333409
`npx omnara secrets delete <secret-id>` for each secret.
410+
With Discord, also delete the application in the Discord Developer Portal.

‎examples/browser-agent/agent.yaml‎

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,17 @@ instruction: |
114114

115115
# Reporting
116116

117-
When this conversation comes from an integration such as Slack, send
118-
updates and results with the integration's qualified posting tool (for
119-
example, `int__engineering__post_message`); people there see only those
120-
messages and your questions. Otherwise reply in the conversation.
117+
When this conversation comes from an integration such as Slack or Discord,
118+
send updates and results with the integration's qualified posting tool
119+
(for example, `int__engineering__post_message`); people there see only
120+
those messages and your questions. Otherwise reply in the conversation.
121121

122122
On long tasks, send a short update at milestones, not after every click.
123123
Attach a screenshot to each update, post one just before each question,
124-
and deliver files from /workspace/output the same way: in Slack, pass each
125-
upload's path in `paths: ["/artifacts/<artifact_id>"]` alongside the
126-
`text`. Finish with what you did, what you found, and anything left undone.
124+
and deliver files from /workspace/output the same way: pass each upload's
125+
path in `paths: ["/artifacts/<artifact_id>"]` alongside the message (`text`
126+
in Slack, `content` in Discord). Finish with what you did, what you found,
127+
and anything left undone.
127128

128129
model:
129130
provider_config: "{{MODEL_PROVIDER_CONFIG}}"
@@ -189,15 +190,8 @@ machine_sources:
189190
chmod +x /workspace/bin/totp
190191
191192
tools:
192-
run_command: {}
193-
read_process: {}
194-
write_process: {}
195-
stop_process: {}
196-
list_processes: {}
197-
list_machines: {}
198-
inspect_machine: {}
199-
upload_file: {}
200-
download_file: {}
193+
# Machine tools such as run_command and upload_file are added automatically;
194+
# list one here only to change its permission.
201195
ask_question: {}
202196
web_search: {}
203197
web_fetch: {}

‎examples/linkedin-signal-agent/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ of at most five posts, each with why it matters and a suggested action:
1111
> **Author:** Jane Doe, Head of Platform at a Series B logistics startup\
1212
> **Suggested action:** reply with how you handle machine failures, disclosing the affiliation.
1313
14-
Reply to it wherever you use it (your own app, Slack, or the Omnara console)
14+
Reply to it wherever you use it (your own app, Slack, Discord, or the Omnara console)
1515
to ask for reply drafts or push back on the filtering. It never posts to
1616
LinkedIn.
1717

0 commit comments

Comments
 (0)