Meeting notes to Slack
Combine voice and apps: transcribe a meeting recording, summarise it into notes and actions with flux-auto, then post the notes to a Slack channel.
This recipe turns a meeting recording into notes your team can read: transcribe the audio, summarise it into decisions and actions, then post the summary in a Slack channel. It uses three Flux abilities on one key.
| Step | Ability | Status |
|---|---|---|
| Transcribe the recording | Speech to text | Over the API: Live. As a tool: Shipping |
| Summarise | Chat with flux-auto | Every key |
| Post to Slack | Apps | Shipping |
The Slack step needs Slack connected to your Flux account. Connected apps are shared by every key on the account, so any key you use here can post as you. See Who can see your connections.
Before you start
- The recording. Any common audio format works (mp3, m4a, wav, ogg, webm, flac), up to 8 MB. Split a longer recording into parts.
- A paid plan. Transcription is a paid ability. See Give your agent abilities.
- Slack connected. Ask your agent to connect it with
apps_connect, or run the connect step in Use apps.
From your agent
Add the Flux tools server to your agent, if you have not already:
Built into Murage, which decides which abilities it uses. Nothing to set up here. See murage.ai.
Built into Wayland, which decides which abilities it uses. Nothing to set up here. See getwayland.com.
Add the Flux tools server from your terminal.
claude mcp add --transport http flux-tools https://api.fluxrouter.ai/mcp-tools/ \
--header "Authorization: Bearer sk-YOUR-FLUX-KEY"
Then ask Claude Code:
Call the Flux list_capabilities tool and tell me what it returns.
From Claude Code's own docs, checked 2026-09-28.
Add the Flux tools server to the same config. Codex reads the key from FLUX_API_KEY, which you exported above. File: ~/.codex/config.toml
[mcp_servers.flux-tools]
url = "https://api.fluxrouter.ai/mcp-tools/"
bearer_token_env_var = "FLUX_API_KEY"
Then ask Codex:
Call the Flux list_capabilities tool and tell me what it returns.
From Codex's own docs, checked 2026-09-28.
Add the Flux tools server to your global MCP config, then restart Cursor. File: ~/.cursor/mcp.json
{
"mcpServers": {
"flux-tools": {
"url": "https://api.fluxrouter.ai/mcp-tools/",
"headers": {
"Authorization": "Bearer sk-YOUR-FLUX-KEY"
}
}
}
}
Then ask Cursor:
Call the Flux list_capabilities tool and tell me what it returns.
From Cursor's own docs, checked 2026-09-28.
Add the Flux tools server to the same config, then restart Hermes. File: ~/.hermes/config.yaml
mcp_servers:
flux-tools:
url: "https://api.fluxrouter.ai/mcp-tools/"
headers:
Authorization: "Bearer sk-YOUR-FLUX-KEY"
Then ask Hermes:
Call the Flux list_capabilities tool and tell me what it returns.
From Hermes's own docs, checked 2026-09-28.
Not checked yet. We have not checked how OpenClaw adds an MCP server, so we do not show a recipe. See OpenClaw's own docs.
Open Cline's MCP servers panel, edit the settings file, and add the Flux tools server.
{
"mcpServers": {
"flux-tools": {
"type": "streamableHttp",
"url": "https://api.fluxrouter.ai/mcp-tools/",
"headers": {
"Authorization": "Bearer sk-YOUR-FLUX-KEY"
}
}
}
}
Then ask Cline:
Call the Flux list_capabilities tool and tell me what it returns.
From Cline's own docs, checked 2026-09-28.
Then ask:
Transcribe https://files.example.com/standup-0928.m4a with the Flux
transcribetool. Summarise it as: decisions, actions (with owner), open questions. Then use the Flux apps tools to post the summary in the #team Slack channel. Find the Slack action withapps_find_actionsfirst.
The agent makes three kinds of call: transcribe once, its own model to write the summary, and apps_find_actions then apps_execute once to post. The transcribe tool takes a public https link (audio_url) or the file inline as base64 (audio_base64 with filename).
If the transcribe tool is not switched on for your key yet, it answers ability_disabled. Transcribe from your own code instead, as below, and hand the text to your agent.
From your own code
Transcribe and summarise with the OpenAI-compatible client, then post through the tools server. The Slack action slug and argument names are an example; take the real ones from apps_find_actions.
import json
import requests
from openai import OpenAI
KEY = "sk-YOUR-FLUX-KEY"
client = OpenAI(base_url="https://api.fluxrouter.ai/v1", api_key=KEY)
# 1. Transcribe. flux-voice picks the model by clip length.
with open("standup-0928.m4a", "rb") as audio:
transcript = client.audio.transcriptions.create(model="flux-voice", file=audio)
# 2. Summarise.
summary = client.chat.completions.create(
model="flux-auto",
messages=[
{"role": "system", "content": "Summarise meeting transcripts as: Decisions, Actions (with owner), Open questions. Be brief."},
{"role": "user", "content": transcript.text},
],
).choices[0].message.content
# 3. Post to Slack through the Flux tools server.
body = {
"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {"name": "apps_execute", "arguments": {
"action": "SLACK_SEND_MESSAGE",
"arguments": {"channel": "#team", "text": summary},
}},
}
res = requests.post(
"https://api.fluxrouter.ai/mcp-tools/",
headers={
"Authorization": f"Bearer {KEY}",
"Content-Type": "application/json",
"Accept": "application/json, text/event-stream",
},
json=body,
timeout=320,
)
res.raise_for_status()
data = next(line[len("data:"):] for line in res.text.splitlines() if line.startswith("data:"))
result = json.loads(data)["result"]["structuredContent"]
print(result.get("error") or result["ok"])
The same in TypeScript:
import fs from 'node:fs';
import OpenAI from 'openai';
const KEY = 'sk-YOUR-FLUX-KEY';
const client = new OpenAI({ baseURL: 'https://api.fluxrouter.ai/v1', apiKey: KEY });
// 1. Transcribe.
const transcript = await client.audio.transcriptions.create({
model: 'flux-voice',
file: fs.createReadStream('standup-0928.m4a'),
});
// 2. Summarise.
const completion = await client.chat.completions.create({
model: 'flux-auto',
messages: [
{ role: 'system', content: 'Summarise meeting transcripts as: Decisions, Actions (with owner), Open questions. Be brief.' },
{ role: 'user', content: transcript.text },
],
});
const summary = completion.choices[0]?.message.content ?? '';
// 3. Post to Slack through the Flux tools server.
const res = await fetch('https://api.fluxrouter.ai/mcp-tools/', {
method: 'POST',
headers: {
Authorization: `Bearer ${KEY}`,
'Content-Type': 'application/json',
Accept: 'application/json, text/event-stream',
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'tools/call',
params: {
name: 'apps_execute',
arguments: { action: 'SLACK_SEND_MESSAGE', arguments: { channel: '#team', text: summary } },
},
}),
});
const line = (await res.text()).split('\n').find((l) => l.startsWith('data:'));
const result = JSON.parse(line!.slice('data:'.length)).result.structuredContent;
console.log(result.error ?? result.ok);
Good to know
- Nothing is rolled back. If the post fails, you still have the transcript and the summary, and you were billed for the transcription. Post again with the same text; do not transcribe again.
- Check before posting twice. If the job might run twice for one meeting, put the recording's name in the message and ask the agent to search the channel for it first.
- Transcripts can hold private details. Read the summary before it goes to a wide channel, or post it to yourself first.
What it costs
- Transcription is billed per second of audio, rounded up, with a minimum. The response's
x-flux-billed-secondsandx-flux-cost-usdheaders show what it cost. Price: $0.10 per minute heard. - The summary is a normal chat call on
flux-auto. - The Slack post is one app action run.
- App actions: priced per call.
If something goes wrong
- The recording is refused as too large or the wrong format: see Speech to text problems.
- The Slack step says
payment_required,rate_limitedorinvalid_request: see App problems.