How to connect your own AI agent to Cade, and every tool it gets, generated from the server's own tool definitions, so it is always what an agent sees in tools/list. A result is text and, matching its schema, structuredContent, so an agent can pass one tool's IDs to the next.
1. In Slack open Cade's Home tab, press Configure, then AI agent and Create key. Cade shows the key to you only, once, with this Cade's MCP endpoint (the same window shows the endpoint again, and whether you have a key). Revoke key in the same window ends it.
2. Add Cade to your agent as a remote MCP server (Streamable HTTP), with the key in the header x-apikey. Replace the two placeholders with the endpoint and key from step 1:
claude mcp add --transport http cade https://YOUR-CADE-WORKER/mcp --header "x-apikey: YOUR_API_KEY"
gemini mcp add --transport http cade https://YOUR-CADE-WORKER/mcp --header "x-apikey: YOUR_API_KEY"
Add a remote MCP server with the endpoint and the header x-apikey set to your key. The Claude.ai and Gemini web apps can't send a custom header, so they can't connect yet.
3. Ask your agent something like "list my Cade tasks". Everything runs as you, so it reads only what you can read, and anything that changes a task or posts a message is shown to you first.
get_taskReads one task from Cade's own database: its details, people, links, summary and notes. It includes no thread, but names the one the task was made from, which get_thread_history reads.
| Name | Type | Required | Notes |
|---|---|---|---|
task_id | string | yes | The task's ID, channel and message time joined by a colon, such as C0123ABCD:1700000000.000100 |
fields | string[]: title | project | channel_id | status | priority | due_date | incident | has_subtasks | blocked | blocked_reason | link | owner | reviewer | tester | summary | summary_by | notes | notes_link | created_by | prs | completed_at | original_thread | original_thread_state | releases | Only these fields, to keep the result small; task_id is always there. Default: all |
| Name | Type | Required | Notes |
|---|---|---|---|
task_id | string | yes | The task's ID, for the other tools |
title | string | The task's title | |
project | string | The project's name | |
channel_id | string | The task's channel ID | |
status | string: TODO | IN_PROGRESS | IN_REVIEW | IN_TESTING | CLIENT_REVIEW | DONE | The task's status | |
priority | string: Urgent | High | Medium | Low | The task's priority | |
due_date | string | DD/MM/YYYY, or empty for none | |
incident | boolean | Whether it is an incident: something broken now, always Urgent | |
has_subtasks | boolean | Whether it is done in parts, so Cade suggests no status changes from messages | |
blocked | boolean | Whether it is blocked: it keeps its status and shows as blocked on its card | |
blocked_reason | string | Why it is blocked, in a short phrase, or empty | |
link | string | A link to the task's message | |
owner | string[] | The task's owners, as Slack user IDs: show their names, not the IDs | |
reviewer | string[] | The task's reviewers, as Slack user IDs: show their names, not the IDs | |
tester | string[] | The task's testers, as Slack user IDs: show their names, not the IDs | |
user_names | object | The names of the people whose user IDs, or <@…> mentions, are in this result, by user ID (at most 50; for any other ID use get_user). Show the name, never the ID | |
created_by | string | Who raised it: a Slack user ID, show the name, not the ID | |
completed_at | string | When it was marked Done, or empty (YYYY-MM-DD HH:MM, UTC) | |
notes_link | string | A link to the notes page, or empty | |
summary | string | The summary of the issue, or empty | |
summary_by | string | Who wrote the summary, or empty: a Slack user ID, show the name, not the ID | |
notes | string | The notes people wrote, or empty | |
original_thread_state | string: found | none | unknown | found: original_thread names it; none: made from no other thread; unknown: no messages kept yet | |
original_thread | object or null | The thread a task was made from, or null | |
original_thread.thread_id | string | The thread's ID, for get_thread_history | |
original_thread.link | string | A link to the thread | |
prs | object[] | The pull requests linked to the task, each with where it is and the release it was sent with · A pull request linked to the task | |
prs[].url | string | yes | The pull request's address |
prs[].label | string | yes | repo/number |
prs[].state | string: PENDING | PENDING_APPROVAL | APPROVED | yes | PENDING: not sent to the client yet; PENDING_APPROVAL: sent, waiting for the approver; APPROVED. A Done task's are all APPROVED |
prs[].release | object or null | yes | The release it was sent with, or null while pending |
prs[].release.release_id | integer | The release's number | |
prs[].release.note | string | What the release completes | |
prs[].release.status | string: PENDING_APPROVAL | APPROVED | PENDING_APPROVAL: waiting for the approver; APPROVED | |
releases | object[] | The partial releases sent to the client for approval, oldest first (those not approved are not kept): which PRs, what they complete, who sent them and who approved · A partial release: pull requests sent to the client for approval before the whole task is done | |
releases[].release_id | integer | yes | The release's number |
releases[].prs | string[] | yes | The pull requests' addresses |
releases[].note | string | yes | What the release completes |
releases[].status | string: PENDING_APPROVAL | APPROVED | NOT_APPROVED | yes | PENDING_APPROVAL: waiting for the approver; APPROVED; NOT_APPROVED: turned down, its PRs are pending again |
releases[].sent_by | string | yes | Who sent the release: a Slack user ID, show the name, not the ID |
releases[].sent_at | string | yes | When it was sent (YYYY-MM-DD HH:MM, UTC) |
releases[].decided_by | string | yes | Who decided it, or empty while waiting: a Slack user ID, show the name, not the ID |
releases[].decided_at | string | yes | When it was decided, or empty (YYYY-MM-DD HH:MM, UTC) |
get_thread_historyReads a whole Slack thread from Slack, oldest message first. Slack's free plan hides messages older than 90 days; for a task Cade tracks, get_task_history has the messages Cade kept.
Give one of thread_id or link.
| Name | Type | Required | Notes |
|---|---|---|---|
thread_id | string | The thread's ID, channel and message time joined by a colon, such as C0123ABCD:1700000000.000100 | |
link | string | Instead of thread_id: a link to a message in the thread, such as https://team.slack.com/archives/C0123ABCD/p1700000000123456 |
| Name | Type | Required | Notes |
|---|---|---|---|
thread_id | string | yes | The thread's ID, for get_thread_history |
channel_name | string | yes | The channel's name |
messages | object[] | yes | Oldest first · A message in a thread |
messages[].ts | string | yes | Slack's message time |
messages[].time | string | yes | When it was sent (YYYY-MM-DD HH:MM, UTC) |
messages[].user_id | string | yes | The sender: a Slack user ID (show the name, not the ID), a bot's name or ID, or unknown |
messages[].bot | boolean | yes | Whether a bot sent it |
messages[].text | string | yes | What it says, with <@U…> mentions as sent |
messages[].files | string[] | yes | Names of attached files |
user_names | object | yes | The names of the people whose user IDs, or <@…> mentions, are in this result, by user ID (at most 50; for any other ID use get_user). Show the name, never the ID |
get_task_historyReads the messages Cade kept of a task's own thread, oldest first: what was done about the task. Unlike get_thread_history it doesn't ask Slack, so it still has messages Slack hides after 90 days.
| Name | Type | Required | Notes |
|---|---|---|---|
task_id | string | yes | The task's ID, channel and message time joined by a colon, such as C0123ABCD:1700000000.000100 |
| Name | Type | Required | Notes |
|---|---|---|---|
task_id | string | yes | The task's ID, for the other tools |
title | string | yes | The task's title |
messages | object[] | yes | Oldest first · A message in a thread |
messages[].ts | string | yes | Slack's message time |
messages[].time | string | yes | When it was sent (YYYY-MM-DD HH:MM, UTC) |
messages[].user_id | string | yes | The sender: a Slack user ID (show the name, not the ID), a bot's name or ID, or unknown |
messages[].bot | boolean | yes | Whether a bot sent it |
messages[].text | string | yes | What it says, with <@U…> mentions as sent |
messages[].files | string[] | yes | Names of attached files |
original_thread | object or null | yes | The thread a task was made from, or null |
original_thread.thread_id | string | The thread's ID, for get_thread_history | |
original_thread.link | string | A link to the thread | |
user_names | object | yes | The names of the people whose user IDs, or <@…> mentions, are in this result, by user ID (at most 50; for any other ID use get_user). Show the name, never the ID |
get_tasksLists Cade tasks, most urgent first: your own or everyone's in the channels you can read, open ones by default. It can also give the tasks done in a period, with those not done, for an executive summary.
| Name | Type | Required | Notes |
|---|---|---|---|
mine | boolean | Only the tasks you are owner, reviewer or tester of | |
role | string: owner | reviewer | tester | Only tasks where you have this role (implies mine) | |
assignee | string | Only tasks this person is on, as a Slack user ID such as U0123ABCD | |
unassigned | boolean | Only tasks nobody is owner, reviewer or tester of | |
status | string: open | all | TODO | IN_PROGRESS | IN_REVIEW | IN_TESTING | CLIENT_REVIEW | DONE | open (default: everything not done), all, or one status | |
project | string | Only this project's tasks, by the name get_projects gives | |
completed_from | string | Only tasks marked Done on or after this day (status defaults to DONE then) (YYYY-MM-DD) | |
completed_to | string | Only tasks marked Done on or before this day (YYYY-MM-DD) | |
include_open | boolean | With completed_from or completed_to: give the tasks not done too, listed first, as well as those done in the days. Can't be combined with status | |
fields | string[]: title | project | channel_id | status | priority | due_date | incident | has_subtasks | blocked | blocked_reason | link | owner | reviewer | tester | summary | summary_by | notes | notes_link | created_by | prs | completed_at | The fields to give for each task, besides task_id which is always there. Default: all but summary, summary_by, notes, notes_link, created_by, prs, completed_at. Add summary or notes to get them for every task listed | |
limit | integer | How many tasks to return, most urgent first. Default 20 · min 1, max 100 |
| Name | Type | Required | Notes |
|---|---|---|---|
total | integer | yes | How many tasks match and you can see |
tasks | object[] | yes | The ones shown, grouped by project, most urgent first within each · Every field, or just those asked for in fields |
tasks[].task_id | string | yes | The task's ID, for the other tools |
tasks[].title | string | The task's title | |
tasks[].project | string | The project's name | |
tasks[].channel_id | string | The task's channel ID | |
tasks[].status | string: TODO | IN_PROGRESS | IN_REVIEW | IN_TESTING | CLIENT_REVIEW | DONE | The task's status | |
tasks[].priority | string: Urgent | High | Medium | Low | The task's priority | |
tasks[].due_date | string | DD/MM/YYYY, or empty for none | |
tasks[].incident | boolean | Whether it is an incident: something broken now, always Urgent | |
tasks[].has_subtasks | boolean | Whether it is done in parts, so Cade suggests no status changes from messages | |
tasks[].blocked | boolean | Whether it is blocked: it keeps its status and shows as blocked on its card | |
tasks[].blocked_reason | string | Why it is blocked, in a short phrase, or empty | |
tasks[].link | string | A link to the task's message | |
tasks[].owner | string[] | The task's owners, as Slack user IDs: show their names, not the IDs | |
tasks[].reviewer | string[] | The task's reviewers, as Slack user IDs: show their names, not the IDs | |
tasks[].tester | string[] | The task's testers, as Slack user IDs: show their names, not the IDs | |
tasks[].summary | string | The summary of the issue, or empty | |
tasks[].summary_by | string | Who wrote the summary, or empty: a Slack user ID, show the name, not the ID | |
tasks[].notes | string | The notes people wrote, or empty | |
tasks[].notes_link | string | A link to the notes page, or empty | |
tasks[].created_by | string | Who raised it: a Slack user ID, show the name, not the ID | |
tasks[].prs | object[] | The pull requests linked to the task, each with its state and the release it was sent with · A pull request linked to the task | |
tasks[].prs[].url | string | yes | The pull request's address |
tasks[].prs[].label | string | yes | repo/number |
tasks[].prs[].state | string: PENDING | PENDING_APPROVAL | APPROVED | yes | PENDING: not sent to the client yet; PENDING_APPROVAL: sent, waiting for the approver; APPROVED. A Done task's are all APPROVED |
tasks[].prs[].release | object or null | yes | The release it was sent with, or null while pending |
tasks[].prs[].release.release_id | integer | The release's number | |
tasks[].prs[].release.note | string | What the release completes | |
tasks[].prs[].release.status | string: PENDING_APPROVAL | APPROVED | PENDING_APPROVAL: waiting for the approver; APPROVED | |
tasks[].completed_at | string | When it was marked Done, or empty (YYYY-MM-DD HH:MM, UTC) | |
user_names | object | yes | The names of the people whose user IDs, or <@…> mentions, are in this result, by user ID (at most 50; for any other ID use get_user). Show the name, never the ID |
get_releasesLists the partial releases of tasks: pull requests sent to the client for approval before the whole task is done. Approving or turning one down is the approver's click in Slack, not a tool.
| Name | Type | Required | Notes |
|---|---|---|---|
status | string: PENDING_APPROVAL | APPROVED | NOT_APPROVED | all | Default PENDING_APPROVAL | |
task_id | string | Only this task's releases | |
project | string | Only this project's tasks, by the name get_projects gives | |
limit | integer | How many releases to return, oldest first. Default 20 · min 1, max 100 |
| Name | Type | Required | Notes |
|---|---|---|---|
total | integer | yes | How many match and you can see |
releases | object[] | yes | The releases that match, oldest first · A release, with its task |
releases[].release_id | integer | yes | The release's number |
releases[].prs | object[] | yes | The release's pull requests · A pull request in the release |
releases[].prs[].url | string | yes | The pull request's address |
releases[].prs[].label | string | yes | repo/number |
releases[].note | string | yes | What the release completes |
releases[].status | string: PENDING_APPROVAL | APPROVED | NOT_APPROVED | yes | PENDING_APPROVAL: waiting for the approver; APPROVED; NOT_APPROVED: turned down, its PRs are pending again |
releases[].sent_by | string | yes | Who sent the release: a Slack user ID, show the name, not the ID |
releases[].sent_at | string | yes | When it was sent (YYYY-MM-DD HH:MM, UTC) |
releases[].decided_by | string | yes | Who decided it, or empty while waiting: a Slack user ID, show the name, not the ID |
releases[].decided_at | string | yes | When it was decided, or empty (YYYY-MM-DD HH:MM, UTC) |
releases[].task_id | string | yes | The task's ID, for the other tools |
releases[].title | string | yes | The task's title |
releases[].project | string | yes | The project's name |
user_names | object | yes | The names of the people whose user IDs, or <@…> mentions, are in this result, by user ID (at most 50; for any other ID use get_user). Show the name, never the ID |
update_releaseChanges a release still waiting for approval: its pull requests and what it completes. Cade updates the approver's request and the task's card, and tells the thread. It never approves or turns a release down: that is the approver's click in Slack. Call this only with changes the person has seen and approved.
| Name | Type | Required | Notes |
|---|---|---|---|
release_id | integer | yes | The release's number, as get_releases gives it · min 1 |
prs | object | Pull requests to add to and remove from the release, as links. Added ones must be linked to the task already (update_task prs.add) and not in another release; a release keeps at least one | |
prs.add | string[] | Pull requests to add to the release, as links | |
prs.remove | string[] | Pull requests to take out of the release, as links; they go back to pending | |
note | string | What the release completes, replacing the earlier note |
| Name | Type | Required | Notes |
|---|---|---|---|
release_id | integer | yes | The release's number |
task_id | string | yes | The task's ID, for the other tools |
changed | boolean | yes | Whether the release changed |
release | object | yes | The release as it is now |
release.release_id | integer | yes | The release's number |
release.prs | string[] | yes | The pull requests' addresses |
release.note | string | yes | What the release completes |
release.status | string: PENDING_APPROVAL | APPROVED | NOT_APPROVED | yes | PENDING_APPROVAL: waiting for the approver; APPROVED; NOT_APPROVED: turned down, its PRs are pending again |
release.sent_by | string | yes | Who sent the release: a Slack user ID, show the name, not the ID |
release.sent_at | string | yes | When it was sent (YYYY-MM-DD HH:MM, UTC) |
release.decided_by | string | yes | Who decided it, or empty while waiting: a Slack user ID, show the name, not the ID |
release.decided_at | string | yes | When it was decided, or empty (YYYY-MM-DD HH:MM, UTC) |
user_names | object | yes | The names of the people whose user IDs, or <@…> mentions, are in this result, by user ID (at most 50; for any other ID use get_user). Show the name, never the ID |
get_channelsLists the Slack channels Cade is in and you can read, project channels first. It is where to start to browse for conversations that should become tasks: pick a channel, then read its threads with get_channel_threads.
| Name | Type | Required | Notes |
|---|---|---|---|
limit | integer | How many channels to return. Default 50 · min 1, max 200 |
| Name | Type | Required | Notes |
|---|---|---|---|
total | integer | yes | How many channels Cade is in that you can read |
channels | object[] | yes | Project channels first, then by name · A channel Cade is in |
channels[].channel_id | string | yes | A Slack channel ID, such as C0123ABCD |
channels[].name | string | yes | The channel's name |
channels[].private | boolean | yes | Whether the channel is private |
channels[].project | string | yes | Set if this is a project's channel, else empty |
get_channel_threadsLists a channel's recent conversations that Cade doesn't track as tasks, newest first. Use it to find conversations that should become tasks: read one with get_thread_history and make the task with create_task.
| Name | Type | Required | Notes |
|---|---|---|---|
channel_id | string | yes | The channel's ID, as get_channels gives it, such as C0123ABCD |
days | integer | How many days back to look. Default 14 · min 1, max 90 | |
with_replies | boolean | Only the messages that have replies, the conversations that happened. Default false: every message of people | |
limit | integer | How many threads to return, newest first. Default 10 · min 1, max 50 |
| Name | Type | Required | Notes |
|---|---|---|---|
channel_id | string | yes | A Slack channel ID, such as C0123ABCD |
channel_name | string | yes | The channel's name |
total | integer | yes | How many matching threads there are in that time |
threads | object[] | yes | Newest first · A conversation that is not a task |
threads[].thread_id | string | yes | For get_thread_history and create_task |
threads[].time | string | yes | When it was sent (YYYY-MM-DD HH:MM, UTC) |
threads[].user_id | string | yes | A Slack user ID, show the name, not the ID |
threads[].text | string | yes | The start of what it says, up to 300 characters, with <@U…> mentions as sent |
threads[].files | string[] | yes | Names of attached files |
threads[].reply_count | integer | yes | How many replies it has |
threads[].last_reply | string | yes | When the last reply was sent, or empty for none (YYYY-MM-DD HH:MM, UTC) |
user_names | object | yes | The names of the people whose user IDs, or <@…> mentions, are in this result, by user ID (at most 50; for any other ID use get_user). Show the name, never the ID |
create_taskCreates a task, or an incident, in a project's channel as the person you act for: from a Slack thread (moved into the new task) or from scratch, with its summary saved on the notes page. An incident is always Urgent and due immediately. Suggest the title, priority, due date and summary and ask for the person's input, and call this only with a task the person has seen and approved. Check with get_tasks that the task doesn't exist already. Each call makes a new task. Offer to assign people afterwards with update_task.
| Name | Type | Required | Notes |
|---|---|---|---|
title | string | yes | One short line saying what has to be done |
project | string | The project to make it in, by the name get_projects gives. Can be left out when the thread is in a project's channel or there is only one project | |
priority | string: Urgent | High | Medium | Low | Default Medium. Not for an incident | |
due_date | string | DD/MM/YYYY or YYYY-MM-DD. Use a date the thread gives or clearly implies, never an invented one; leave out for none. Not for an incident | |
incident | boolean | Make an incident: only for something broken now that blocks people or the business, always Urgent and due immediately. When unsure, leave it false (a task). Default false | |
summary | string | The summary of the issue only, saved on the notes page: what the problem or request is, who raised it and when, the impact and the details needed to understand it, for someone who wasn't in the discussion. Write it from the thread it is made from, and leave out what that thread doesn't say. Plain text, people's names rather than @mentions. At most 8000 characters | |
thread_id | string | The thread to make it from. One that is already a task, was moved into one, or is a bot's or a direct message can't be used | |
link | string | Instead of thread_id: a link to a message in the thread |
| Name | Type | Required | Notes |
|---|---|---|---|
task_id | string | yes | The task's ID, for the other tools |
link | string | yes | A link to the task's message |
project | string | yes | The project's name |
incident | boolean | yes | Whether it was made as an incident |
summary_saved | boolean | yes | Whether the summary was saved on the notes page |
notes_link | string | yes | A link to the notes page, or empty |
get_projectsLists the projects Cade tracks tasks for, in the channels you can read.
None.
| Name | Type | Required | Notes |
|---|---|---|---|
total | integer | yes | How many projects you can see |
projects | object[] | yes | The projects you can see · A project |
projects[].name | string | yes | The project's name |
projects[].channel_id | string | yes | The project's channel ID |
get_userGives a Slack user's name from their ID or mention, and with profile also their email, phone number and job title.
| Name | Type | Required | Notes |
|---|---|---|---|
user_id | string | yes | A Slack user ID such as U0123ABCD, or a <@…> mention |
profile | boolean | Also give their email, phone number and title. Private: ask for it only when needed, such as to reach someone on WhatsApp (https://wa.me/<number with country code, digits only>?text=<URL-encoded message> opens the chat). Default false |
| Name | Type | Required | Notes |
|---|---|---|---|
user_id | string | yes | A Slack user ID, show the name, not the ID |
name | string | yes | Real name |
handle | string | yes | Display name, or empty |
profile | object or null | yes | Only when asked for with profile, otherwise null |
profile.email | string | Or empty | |
profile.phone | string | Or empty | |
profile.title | string | Or empty |
get_usersLists the people of the Slack workspace with their user IDs, leaving out bots and deactivated accounts. In a large workspace use find_user_by_name instead.
| Name | Type | Required | Notes |
|---|---|---|---|
limit | integer | How many people to return. Default 50 · min 1, max 200 | |
fields | string[]: name | username | Only these fields for each person, to keep the result small; user_id is always there. Default: all |
| Name | Type | Required | Notes |
|---|---|---|---|
total | integer | yes | How many people there are |
users | object[] | yes | The people, with their user IDs · A person in the workspace |
users[].user_id | string | yes | A Slack user ID, show the name, not the ID |
users[].name | string | Real name | |
users[].username | string | Slack username |
get_team_availabilityShows who in the team has room for work, least loaded first: their open tasks, how many are overdue or urgent, their Slack status and time zone. Use it to pick whom to assign a task to.
| Name | Type | Required | Notes |
|---|---|---|---|
users | string[] | Only these people, as Slack user IDs such as U0123ABCD | |
project | string | Count only this project's tasks, and cover only the people picked as working on it (everyone if none were picked). The project's name, as get_projects gives it | |
fields | string[]: name | open_tasks | owner | reviewer | tester | overdue | urgent_or_high | status | status_until | time_zone | away | presence | The fields to give, to keep the result small; user_id is always there. Default: all but presence. Add presence to look up whether the person is active in Slack right now (one Slack call each) | |
limit | integer | How many people to return, least loaded first. Default 50 · min 1, max 200 |
| Name | Type | Required | Notes |
|---|---|---|---|
total | integer | yes | How many people were looked at |
people | object[] | yes | Least loaded first, people with an away status last · A person's load and availability |
people[].user_id | string | yes | A Slack user ID, show the name, not the ID |
people[].name | string | Real name | |
people[].open_tasks | integer | Open tasks they are owner, reviewer or tester of | |
people[].owner | integer | Open tasks they are the owner of | |
people[].reviewer | integer | Open tasks they are the reviewer of | |
people[].tester | integer | Open tasks they are the tester of | |
people[].overdue | integer | Open tasks past their due date | |
people[].urgent_or_high | integer | Open Urgent or High priority tasks | |
people[].status | string | Their Slack status text, or empty | |
people[].status_until | string | When the status ends, in UTC, or empty (YYYY-MM-DD) | |
people[].time_zone | string | Their time zone, such as Asia/Colombo | |
people[].presence | string: active | away | unknown | Only when asked for in fields. 'away' often only means Slack is closed, so it is a weak sign that someone is unavailable | |
people[].away | boolean | Whether the status text suggests vacation, sick leave or being out of office: don't assign someone who is away |
get_availabilityShows how much room one person has for work: their open tasks, how many are overdue or urgent, their Slack status and time zone. To compare the whole team use get_team_availability.
| Name | Type | Required | Notes |
|---|---|---|---|
user_id | string | yes | The person, as a Slack user ID such as U0123ABCD |
project | string | Count only this project's tasks. If the project has people picked, the person must be one of them. The project's name, as get_projects gives it | |
fields | string[]: name | open_tasks | owner | reviewer | tester | overdue | urgent_or_high | status | status_until | time_zone | away | presence | The fields to give, to keep the result small; user_id is always there. Default: all but presence. Add presence to look up whether the person is active in Slack right now (one Slack call each) |
| Name | Type | Required | Notes |
|---|---|---|---|
person | object | yes | A person's load and availability |
person.user_id | string | yes | A Slack user ID, show the name, not the ID |
person.name | string | Real name | |
person.open_tasks | integer | Open tasks they are owner, reviewer or tester of | |
person.owner | integer | Open tasks they are the owner of | |
person.reviewer | integer | Open tasks they are the reviewer of | |
person.tester | integer | Open tasks they are the tester of | |
person.overdue | integer | Open tasks past their due date | |
person.urgent_or_high | integer | Open Urgent or High priority tasks | |
person.status | string | Their Slack status text, or empty | |
person.status_until | string | When the status ends, in UTC, or empty (YYYY-MM-DD) | |
person.time_zone | string | Their time zone, such as Asia/Colombo | |
person.presence | string: active | away | unknown | Only when asked for in fields. 'away' often only means Slack is closed, so it is a weak sign that someone is unavailable | |
person.away | boolean | Whether the status text suggests vacation, sick leave or being out of office: don't assign someone who is away |
find_user_by_nameFinds people in the Slack workspace by part of their name and gives each one's user ID, which update_task takes to assign someone and get_tasks takes as assignee.
| Name | Type | Required | Notes |
|---|---|---|---|
name | string | yes | Part of the person's name, such as Ann or ann.lee |
fields | string[]: name | username | Only these fields for each person, to keep the result small; user_id is always there. Default: all |
| Name | Type | Required | Notes |
|---|---|---|---|
total | integer | yes | How many people match |
users | object[] | yes | Up to 10 of them · A person in the workspace |
users[].user_id | string | yes | A Slack user ID, show the name, not the ID |
users[].name | string | Real name | |
users[].username | string | Slack username |
send_task_messagePosts a message in a task's own thread in Slack as Cade, with a line under it saying who it is from. A mention notifies that person; @channel, @here and @everyone are not sent as mentions. Call this only with text the person has seen and approved.
| Name | Type | Required | Notes |
|---|---|---|---|
task_id | string | yes | The task's ID, channel and message time joined by a colon, such as C0123ABCD:1700000000.000100 |
text | string | yes | The message, as plain text, written as the person would. Mention a person as <@U0123ABCD>, with their user ID and never their name: only the ID notifies them, and a name written out notifies no one. The preview shows the name, but the call keeps the ID. At most 3000 characters |
summary_id | integer | An executive summary's number, as get_executive_summary gives it. Give it when the message tells the thread what a client call decided (see update_executive_summary_after_call): Cade then marks the task as told, and refuses to send if it was told already · min 1 |
| Name | Type | Required | Notes |
|---|---|---|---|
task_id | string | yes | The task's ID, for the other tools |
sent | boolean | yes | Whether the message was posted |
link | string | yes | A link to the task's thread, or empty |
update_taskChanges a task in one call: its status, priority, due date, people, pull requests and the summary on its notes page. Cade posts the field changes in the task's thread and asks the people it assigns to pick it up; the summary is saved quietly. Call this only with changes the person has seen and approved.
| Name | Type | Required | Notes |
|---|---|---|---|
task_id | string | yes | The task's ID, channel and message time joined by a colon, such as C0123ABCD:1700000000.000100 |
status | string: TODO | IN_PROGRESS | IN_REVIEW | IN_TESTING | CLIENT_REVIEW | DONE | The task's new status. A task in Client review can't be changed here: its approver decides | |
priority | string: Urgent | High | Medium | Low | The task's new priority. An incident's never changes | |
due_date | string | DD/MM/YYYY or YYYY-MM-DD, or "none" to remove the due date. Use a date the thread gives or clearly implies, never an invented one. An incident's never changes | |
blocked | boolean | true to mark the task blocked, false to unblock it. A blocked task keeps its status and shows as blocked on its card. Mark it only when the thread says it cannot go on until something else happens | |
blocked_reason | string | Why it is blocked, in a short phrase of at most 100 characters (with blocked: true). Replaces the earlier reason | |
has_subtasks | boolean | true when the task is done in parts (subtasks): Cade then suggests no status changes from people's messages, and the status is set by hand. Pull requests are still tracked | |
summary | string | The summary of the task's issue only: what the problem or request is, who raised it and when, the impact and the details needed to understand it, for someone who wasn't in the discussion. Write it from the thread the task was made from (get_task names it; if there is none, from the task's own thread), and leave out what that thread doesn't say, and what was done and how it ended. Plain text, short paragraphs, "- " for bullets, people's names rather than @mentions. At most 8000 characters. Replaces any earlier one | |
prs | object | Pull requests (GitHub, GitLab or Bitbucket) to link to and unlink from the task, as links. Adding asks the task's reviewers to review; one already sent to the client for approval can't be unlinked here. Cade can't see repositories, so check a pull request with your own tools first | |
prs.add | string[] | Pull requests to link to the task, as links | |
prs.remove | string[] | Pull requests to unlink from the task, as links | |
owner | object | Who to add to and remove from the task's owners | |
owner.add | string[] | Who to add, as Slack user IDs such as U0123ABCD | |
owner.remove | string[] | Who to remove, as Slack user IDs such as U0123ABCD | |
reviewer | object | Who to add to and remove from the task's reviewers | |
reviewer.add | string[] | Who to add, as Slack user IDs such as U0123ABCD | |
reviewer.remove | string[] | Who to remove, as Slack user IDs such as U0123ABCD | |
tester | object | Who to add to and remove from the task's testers | |
tester.add | string[] | Who to add, as Slack user IDs such as U0123ABCD | |
tester.remove | string[] | Who to remove, as Slack user IDs such as U0123ABCD |
| Name | Type | Required | Notes |
|---|---|---|---|
task_id | string | yes | The task's ID, for the other tools |
changed | boolean | yes | Whether a field changed (and was posted in the thread) |
summary_saved | boolean | yes | Whether the summary was saved on the notes page |
notes_link | string | yes | A link to the notes page, or empty |
send_approval_requestAsks a person to approve a task that is in Client review: posts a request in the task's thread that mentions them, with Approve and Not approve buttons only they can click. Approving moves the task to Done; not approving sends it back to In progress. Call this only with an approver the person has chosen and approved. Each call posts a new request.
| Name | Type | Required | Notes |
|---|---|---|---|
task_id | string | yes | The task's ID, channel and message time joined by a colon, such as C0123ABCD:1700000000.000100 |
approver | string | yes | Who approves it, as a Slack user ID such as U0123ABCD: the client, or whoever handles them. find_user_by_name gives it |
| Name | Type | Required | Notes |
|---|---|---|---|
task_id | string | yes | The task's ID, for the other tools |
approver | string | yes | Who was asked: a Slack user ID, show the name, not the ID |
link | string | yes | A link to the task's thread, or empty |
user_names | object | yes | The names of the people whose user IDs, or <@…> mentions, are in this result, by user ID (at most 50; for any other ID use get_user). Show the name, never the ID |
get_server_infoGives the version of Cade's tool set the server has now and the one this session loaded, and says whether the person should disconnect and connect Cade again to load the new tools.
None.
| Name | Type | Required | Notes |
|---|---|---|---|
server_version | string | yes | Cade's version |
toolset_version | string | yes | The version of the tool set the server has now: it changes whenever a tool, a description or the instructions change |
session_toolset_version | string | yes | The version of the tool set this session loaded when it connected, or empty if the client doesn't say |
status | string: CURRENT | OUTDATED | UNKNOWN | yes | CURRENT: this session has the latest tools; OUTDATED: the person should disconnect and connect again; UNKNOWN: the client doesn't say which it loaded |
get_executive_summaryReads an executive summary Cade kept of a project: what it said of each task as written and as agreed after the client call, and whether each task's thread has been told. It is where to start to write the next summary: its period ends where the next begins, and get_tasks (completed_from, completed_to, include_open) gives the tasks to cover.
| Name | Type | Required | Notes |
|---|---|---|---|
project | string | yes | The project, by the name get_projects gives |
date | string | The summary in force on that day. Default: the last one (YYYY-MM-DD) |
| Name | Type | Required | Notes |
|---|---|---|---|
project | string | yes | The project's name |
summary | object or null | yes | The summary, or null if the project has none yet |
summary.summary_id | integer | For get_executive_summary_doc and update_executive_summary_after_call | |
summary.created_at | string | When it was written (YYYY-MM-DD HH:MM, UTC) | |
summary.created_by | string | Who wrote the summary: a Slack user ID, show the name, not the ID | |
summary.from | string | First day of its period (YYYY-MM-DD) | |
summary.to | string | Last day of its period (YYYY-MM-DD) | |
summary.doc_url | string | Where it is in the Google Doc | |
summary.call | object or null | What was said of the call as a whole, or null until it was recorded | |
summary.call.notes | string | What was said of the call | |
summary.call.recorded_by | string | Who recorded the call: a Slack user ID, show the name, not the ID | |
summary.call.recorded_at | string | When it was recorded (YYYY-MM-DD HH:MM, UTC) | |
summary.items | object[] | Each task with the summary as written (before) and as agreed after the call (after) · A task's line in the summary | |
summary.items[].task_id | string | yes | Empty for something added in the call that has no task |
summary.items[].title | string | yes | The task's title when it was written |
summary.items[].status | string | yes | Its status when it was written |
summary.items[].incident | boolean | yes | Whether the task is an incident |
summary.items[].kind | string: COMPLETED | ACTIVE | ADDED | yes | COMPLETED: done in the period; ACTIVE: not done; ADDED: added in the call |
summary.items[].before | object or null | yes | As written; null for what the call added |
summary.items[].before.included | boolean | Whether the summary mentions it | |
summary.items[].before.health | string or null: ON_TRACK | AT_RISK | DELAYED | BLOCKED | | For active work | |
summary.items[].before.progress | string | Short free text, such as 3/5 | |
summary.items[].before.notes | string | One point per line | |
summary.items[].after | object or null | yes | As agreed after the call; null until the call is recorded |
summary.items[].after.included | boolean | Whether the summary mentions it | |
summary.items[].after.health | string or null: ON_TRACK | AT_RISK | DELAYED | BLOCKED | | For active work | |
summary.items[].after.progress | string | Short free text, such as 3/5 | |
summary.items[].after.notes | string | One point per line | |
summary.items[].change | string: pending | unchanged | changed | removed | added | yes | pending: no call recorded yet |
summary.items[].informed_at | string | yes | When the task's thread was told about this change, or empty. Tell it only if this is empty (YYYY-MM-DD HH:MM, UTC) |
earlier | object[] | yes | The project's other summaries, newest first (at most 10) · Another summary of the project |
earlier[].summary_id | integer | yes | The executive summary's number |
earlier[].created_at | string | yes | When it was written (YYYY-MM-DD HH:MM, UTC) |
earlier[].from | string | yes | A day, YYYY-MM-DD |
earlier[].to | string | yes | A day, YYYY-MM-DD |
user_names | object | yes | The names of the people whose user IDs, or <@…> mentions, are in this result, by user ID (at most 50; for any other ID use get_user). Show the name, never the ID |
get_executive_summary_docReads a summary's section from the project's Google Doc as it reads now, after people edited it, such as in the client call. Compare it with get_executive_summary to find what the call changed, then record it with update_executive_summary_after_call.
| Name | Type | Required | Notes |
|---|---|---|---|
project | string | yes | The project, by the name get_projects gives |
summary_id | integer | The summary, as get_executive_summary gives it. Default: the last one · min 1 |
| Name | Type | Required | Notes |
|---|---|---|---|
project | string | yes | The project's name |
summary_id | integer | yes | The executive summary's number |
doc_url | string | yes | Where it is in the Google Doc |
lines | object[] | yes | The section's lines, in order · A line of the section |
lines[].type | string: heading | paragraph | item | yes | What kind of line it is |
lines[].level | integer | yes | How deeply it is nested, 0 for the top |
lines[].text | string | yes | The line's text |
lines[].task_id | string | yes | The task the line links to, or empty |
lines[].written | boolean | yes | Whether Cade wrote this line (false: people added it) |
create_executive_summaryWrites an executive summary to the top of the project's Google Doc (its Summary tab) and keeps what it says of each task. Each call writes a new one. Call this only with a summary the person has seen and approved.
| Name | Type | Required | Notes |
|---|---|---|---|
project | string | yes | The project, by the name get_projects gives |
from | string | First day of the period (YYYY-MM-DD). Default: the day after the last summary's period, or 7 days ago if there is none | |
to | string | Last day of the period (YYYY-MM-DD). Default: today | |
items | object[] | A line for each task the person said something about. A task not listed keeps what the last summary said (an active one with none is ON_TRACK) and completed ones are included; the result names the active ones it carried over. Only tasks of the project completed in the period or not done can be listed · A task's line in the summary | |
items[].task_id | string | yes | The task's ID, channel and message time joined by a colon, such as C0123ABCD:1700000000.000100 |
items[].included | boolean | Whether the summary mentions it. Default true | |
items[].health | string: ON_TRACK | AT_RISK | DELAYED | BLOCKED | ON_TRACK, AT_RISK, DELAYED or BLOCKED, for work not done. Judge it from what the tasks and threads show, never guess | |
items[].progress | string | Short free text, such as 3/5 or 2 of 4 CRMs live, from what the tasks show | |
items[].notes | string | One point per line |
| Name | Type | Required | Notes |
|---|---|---|---|
project | string | yes | The project's name |
summary_id | integer | yes | For get_executive_summary_doc and update_executive_summary_after_call |
from | string | yes | A day, YYYY-MM-DD |
to | string | yes | A day, YYYY-MM-DD |
doc_url | string | yes | Where it is in the Google Doc |
carried_over | string[] | yes | Task IDs of the active tasks you didn't list, which kept what the last summary said |
update_executive_summary_after_callRecords the summary as it was agreed in the client call, next to the summary as it was written, so both are kept and can be compared. It posts nothing and changes no task or Google Doc. After it, tell each changed task's thread with send_task_message (summary_id), and offer create_task, one at a time, for what the call added. Call this only with what the person has seen and approved.
| Name | Type | Required | Notes |
|---|---|---|---|
summary_id | integer | yes | The summary, as get_executive_summary gives it · min 1 |
items | object[] | The tasks whose health, progress, notes or inclusion the call changed (included false takes one out). The after version starts as the written one. Recording again replaces the earlier recording, but a task whose thread was told keeps that unless it changed again · A task whose line the call changed | |
items[].task_id | string | yes | The task's ID, channel and message time joined by a colon, such as C0123ABCD:1700000000.000100 |
items[].included | boolean | Whether the summary mentions it | |
items[].health | string: ON_TRACK | AT_RISK | DELAYED | BLOCKED | ON_TRACK, AT_RISK, DELAYED or BLOCKED, for work not done. Judge it from what the tasks and threads show, never guess | |
items[].progress | string | Short free text, such as 3/5 or 2 of 4 CRMs live, from what the tasks show | |
items[].notes | string | One point per line | |
added | object[] | What the call added: a title for each, with task_id if it is already a task · Something the call added | |
added[].title | string | yes | What was added |
added[].task_id | string | The task's ID, channel and message time joined by a colon, such as C0123ABCD:1700000000.000100 | |
added[].health | string: ON_TRACK | AT_RISK | DELAYED | BLOCKED | ON_TRACK, AT_RISK, DELAYED or BLOCKED, for work not done. Judge it from what the tasks and threads show, never guess | |
added[].progress | string | Short free text, such as 3/5 or 2 of 4 CRMs live, from what the tasks show | |
added[].notes | string | One point per line | |
notes | string | Anything about the call as a whole |
| Name | Type | Required | Notes |
|---|---|---|---|
summary_id | integer | yes | The executive summary's number |
changed | string[] | yes | Task IDs whose summary line the call changed or took out |
added | integer | yes | How many items the call added |