Skip to content

Commit a64ce49

Browse files
authored
feat(incidentio): add on-call, alert, catalog, and team tools (#6529)
* feat(incidentio): add on-call, alert, catalog, and team tools Adds 19 tools to the incident.io block, taking it from 46 to 65 operations. Every endpoint, param, and response field is taken from the official OpenAPI spec at api.incident.io/v1/openapiV3.json. Who is on call had no reachable answer before: the data lives in ScheduleV2.current_shifts, and both schedules_list and schedules_show returned it but never declared it. The new incidentio_on_call_now tool flattens current and upcoming shifts to one row per person, and the two existing schedule tools now declare the fields they were already returning. Also fixes two pre-existing wiring bugs: the block declared an output named schedule_override while the tool emits override, and the on-call handoff skill described a lookup the integration could not perform. * fix(incidentio): stop the alert filter sentinel reaching the API The has_notes and include_maintenance_window dropdowns default to the string "any", meaning "do not filter". The params transform skipped the key in that case, but the executor merges its output over the raw inputs (`{ ...inputs, ...transformedParams }`), so the sentinel survived and the tool sent has_notes[is]=any, which incident.io rejects. The transform now always assigns the key, mapping "any" to undefined so it overwrites the sentinel instead of leaving it in place. The tool also only serializes these filters when it actually has a boolean. Adds tests covering the sentinel, both real boolean values, and the documented bracket-operator filter syntax.
1 parent 1a39e29 commit a64ce49

31 files changed

Lines changed: 4454 additions & 18 deletions

apps/docs/content/docs/en/integrations/incidentio.mdx

Lines changed: 640 additions & 0 deletions
Large diffs are not rendered by default.

apps/sim/blocks/blocks/incidentio.ts

Lines changed: 674 additions & 12 deletions
Large diffs are not rendered by default.

apps/sim/lib/integrations/integrations.json

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"updatedAt": "2026-08-09",
2+
"updatedAt": "2026-08-11",
33
"integrations": [
44
{
55
"type": "onepassword",
@@ -9835,9 +9835,85 @@
98359835
{
98369836
"name": "Delete Escalation Path",
98379837
"description": "Delete an escalation path in incident.io"
9838+
},
9839+
{
9840+
"name": "Get Who Is On Call",
9841+
"description": "Get who is currently on call in incident.io, as one row per ongoing shift across every schedule (or a single schedule). Also returns the shifts that take over at the next changeover."
9842+
},
9843+
{
9844+
"name": "List Schedule Overrides",
9845+
"description": "List the one-off overrides layered on top of a schedule in incident.io, such as someone covering a colleague’s shift"
9846+
},
9847+
{
9848+
"name": "List Alerts",
9849+
"description": "List alerts in incident.io, optionally filtered by status, source, or created date"
9850+
},
9851+
{
9852+
"name": "Show Alert",
9853+
"description": "Get a single alert by ID from incident.io"
9854+
},
9855+
{
9856+
"name": "Resolve Alert",
9857+
"description": "Resolve a currently firing alert in incident.io. Resolving an already-resolved alert is a no-op and returns it unchanged."
9858+
},
9859+
{
9860+
"name": "Create Alert Event",
9861+
"description": "Fire an alert into incident.io through an HTTP alert source. Send the same deduplication key with status \"resolved\" to close the alert you opened."
9862+
},
9863+
{
9864+
"name": "List Incident Alerts",
9865+
"description": "List the connections between incidents and alerts in incident.io — which alerts triggered an incident, or which incident an alert was attached to"
9866+
},
9867+
{
9868+
"name": "Cancel Escalation",
9869+
"description": "Cancel an escalation in incident.io. Notifications stop, and the escalation will not advance to further levels or repeat."
9870+
},
9871+
{
9872+
"name": "List Catalog Types",
9873+
"description": "List all catalog types in incident.io, including those synced from external resources. Use this to find the catalog type ID needed to list entries."
9874+
},
9875+
{
9876+
"name": "List Catalog Entries",
9877+
"description": "List the entries of a catalog type in incident.io — for example every service, team, or customer recorded in the catalog"
9878+
},
9879+
{
9880+
"name": "List Teams",
9881+
"description": "List all teams in the incident.io organisation, along with their members"
9882+
},
9883+
{
9884+
"name": "Show Team",
9885+
"description": "Get a single team by ID from incident.io, along with its members"
9886+
},
9887+
{
9888+
"name": "Create Follow-up",
9889+
"description": "Create a new follow-up on an incident in incident.io"
9890+
},
9891+
{
9892+
"name": "Update Follow-up",
9893+
"description": "Update an existing follow-up in incident.io, for example to mark it completed or reassign it"
9894+
},
9895+
{
9896+
"name": "Create Action",
9897+
"description": "Create a new action on an incident in incident.io"
9898+
},
9899+
{
9900+
"name": "Update Action",
9901+
"description": "Update an existing action in incident.io, for example to mark it completed or reassign it"
9902+
},
9903+
{
9904+
"name": "List Incident Participants",
9905+
"description": "List the participants of an incident in incident.io, split into those actively helping and those just observing"
9906+
},
9907+
{
9908+
"name": "Grant Incident Membership",
9909+
"description": "Make a user a member of a private incident in incident.io"
9910+
},
9911+
{
9912+
"name": "Revoke Incident Membership",
9913+
"description": "Revoke a user's membership of a private incident in incident.io"
98389914
}
98399915
],
9840-
"operationCount": 46,
9916+
"operationCount": 65,
98419917
"triggers": [
98429918
{
98439919
"id": "incidentio_incident_created",

apps/sim/tools/generated/tool-ids.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

apps/sim/tools/generated/tool-metadata.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

apps/sim/tools/generated/tool-outputs.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import {
2+
INCIDENTIO_ACTION_RECORD_OUTPUT_PROPERTIES,
3+
type IncidentioActionsCreateParams,
4+
type IncidentioActionsCreateResponse,
5+
} from '@/tools/incidentio/types'
6+
import type { ToolConfig } from '@/tools/types'
7+
8+
export const actionsCreateTool: ToolConfig<
9+
IncidentioActionsCreateParams,
10+
IncidentioActionsCreateResponse
11+
> = {
12+
id: 'incidentio_actions_create',
13+
name: 'Create Action',
14+
description: 'Create a new action on an incident in incident.io',
15+
version: '1.0.0',
16+
17+
params: {
18+
apiKey: {
19+
type: 'string',
20+
required: true,
21+
visibility: 'user-only',
22+
description: 'incident.io API Key',
23+
},
24+
incident_id: {
25+
type: 'string',
26+
required: true,
27+
visibility: 'user-or-llm',
28+
description:
29+
'The ID of the incident the action belongs to (e.g., "01FDAG4SAP5TYPT98WGR2N7W91")',
30+
},
31+
description: {
32+
type: 'string',
33+
required: true,
34+
visibility: 'user-or-llm',
35+
description: 'Description of the action. Supports Markdown.',
36+
},
37+
assignee_id: {
38+
type: 'string',
39+
required: false,
40+
visibility: 'user-or-llm',
41+
description: 'ID of the user to assign this action to',
42+
},
43+
},
44+
45+
request: {
46+
url: 'https://api.incident.io/v2/actions',
47+
method: 'POST',
48+
headers: (params) => ({
49+
'Content-Type': 'application/json',
50+
Authorization: `Bearer ${params.apiKey}`,
51+
}),
52+
body: (params) => {
53+
const body: Record<string, unknown> = {
54+
incident_id: params.incident_id.trim(),
55+
description: params.description,
56+
}
57+
58+
if (params.assignee_id) body.assignee_id = params.assignee_id.trim()
59+
60+
return body
61+
},
62+
},
63+
64+
transformResponse: async (response: Response) => {
65+
const data = await response.json()
66+
67+
return {
68+
success: true,
69+
output: {
70+
action: data.action,
71+
},
72+
}
73+
},
74+
75+
outputs: {
76+
action: {
77+
type: 'object',
78+
description: 'The created action',
79+
properties: INCIDENTIO_ACTION_RECORD_OUTPUT_PROPERTIES,
80+
},
81+
},
82+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import {
2+
INCIDENTIO_ACTION_RECORD_OUTPUT_PROPERTIES,
3+
type IncidentioActionsUpdateParams,
4+
type IncidentioActionsUpdateResponse,
5+
} from '@/tools/incidentio/types'
6+
import type { ToolConfig } from '@/tools/types'
7+
8+
export const actionsUpdateTool: ToolConfig<
9+
IncidentioActionsUpdateParams,
10+
IncidentioActionsUpdateResponse
11+
> = {
12+
id: 'incidentio_actions_update',
13+
name: 'Update Action',
14+
description:
15+
'Update an existing action in incident.io, for example to mark it completed or reassign it',
16+
version: '1.0.0',
17+
18+
params: {
19+
apiKey: {
20+
type: 'string',
21+
required: true,
22+
visibility: 'user-only',
23+
description: 'incident.io API Key',
24+
},
25+
id: {
26+
type: 'string',
27+
required: true,
28+
visibility: 'user-or-llm',
29+
description: 'The ID of the action to update (e.g., "01FCNDV6P870EA6S7TK1DSYDG0")',
30+
},
31+
description: {
32+
type: 'string',
33+
required: true,
34+
visibility: 'user-or-llm',
35+
description:
36+
'Description of the action. This endpoint replaces the description, so always send it.',
37+
},
38+
status: {
39+
type: 'string',
40+
required: true,
41+
visibility: 'user-or-llm',
42+
description:
43+
'Status of the action: "outstanding", "completed", or "not_doing". Deleting is not supported here.',
44+
},
45+
assignee_id: {
46+
type: 'string',
47+
required: false,
48+
visibility: 'user-or-llm',
49+
description: 'ID of the user to assign this action to',
50+
},
51+
},
52+
53+
request: {
54+
url: (params) => `https://api.incident.io/v2/actions/${encodeURIComponent(params.id.trim())}`,
55+
method: 'PUT',
56+
headers: (params) => ({
57+
'Content-Type': 'application/json',
58+
Authorization: `Bearer ${params.apiKey}`,
59+
}),
60+
body: (params) => {
61+
const body: Record<string, unknown> = {
62+
description: params.description,
63+
status: params.status,
64+
}
65+
66+
if (params.assignee_id) body.assignee_id = params.assignee_id.trim()
67+
68+
return body
69+
},
70+
},
71+
72+
transformResponse: async (response: Response) => {
73+
const data = await response.json()
74+
75+
return {
76+
success: true,
77+
output: {
78+
action: data.action,
79+
},
80+
}
81+
},
82+
83+
outputs: {
84+
action: {
85+
type: 'object',
86+
description: 'The updated action',
87+
properties: INCIDENTIO_ACTION_RECORD_OUTPUT_PROPERTIES,
88+
},
89+
},
90+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import type {
2+
IncidentioAlertEventsCreateParams,
3+
IncidentioAlertEventsCreateResponse,
4+
} from '@/tools/incidentio/types'
5+
import { parseIncidentioJsonParam } from '@/tools/incidentio/utils'
6+
import type { ToolConfig } from '@/tools/types'
7+
8+
export const alertEventsCreateTool: ToolConfig<
9+
IncidentioAlertEventsCreateParams,
10+
IncidentioAlertEventsCreateResponse
11+
> = {
12+
id: 'incidentio_alert_events_create',
13+
name: 'Create Alert Event',
14+
description:
15+
'Fire an alert into incident.io through an HTTP alert source. Send the same deduplication key with status "resolved" to close the alert you opened.',
16+
version: '1.0.0',
17+
18+
params: {
19+
alert_source_config_id: {
20+
type: 'string',
21+
required: true,
22+
visibility: 'user-or-llm',
23+
description:
24+
'The ID of the HTTP alert source config to fire into (e.g., "01GW2G3V0S59R238FAHPDS1R66")',
25+
},
26+
alert_source_token: {
27+
type: 'string',
28+
required: true,
29+
visibility: 'user-only',
30+
description:
31+
'The token generated when configuring the HTTP alert source. This is not the incident.io API key.',
32+
},
33+
title: {
34+
type: 'string',
35+
required: true,
36+
visibility: 'user-or-llm',
37+
description: 'Title of the alert (e.g., "Payments service error rate above 5%")',
38+
},
39+
status: {
40+
type: 'string',
41+
required: true,
42+
visibility: 'user-or-llm',
43+
description: 'Current status of the alert: "firing" or "resolved"',
44+
},
45+
description: {
46+
type: 'string',
47+
required: false,
48+
visibility: 'user-or-llm',
49+
description: 'Detail to add below the title. Supports Markdown.',
50+
},
51+
deduplication_key: {
52+
type: 'string',
53+
required: false,
54+
visibility: 'user-or-llm',
55+
description:
56+
'Key that uniquely identifies this alert. Reuse it to update or resolve the same alert instead of creating a new one.',
57+
},
58+
source_url: {
59+
type: 'string',
60+
required: false,
61+
visibility: 'user-or-llm',
62+
description: 'Link back to the alert in the upstream system',
63+
},
64+
metadata: {
65+
type: 'string',
66+
required: false,
67+
visibility: 'user-or-llm',
68+
description:
69+
'Additional metadata as a JSON object, parsed according to the alert source config (e.g., {"service": "payments"})',
70+
},
71+
},
72+
73+
request: {
74+
url: (params) =>
75+
`https://api.incident.io/v2/alert_events/http/${encodeURIComponent(
76+
params.alert_source_config_id.trim()
77+
)}`,
78+
method: 'POST',
79+
headers: (params) => ({
80+
'Content-Type': 'application/json',
81+
Authorization: `Bearer ${params.alert_source_token}`,
82+
}),
83+
body: (params) => {
84+
const body: Record<string, unknown> = {
85+
title: params.title,
86+
status: params.status,
87+
}
88+
89+
if (params.description) body.description = params.description
90+
if (params.deduplication_key) body.deduplication_key = params.deduplication_key
91+
if (params.source_url) body.source_url = params.source_url
92+
if (params.metadata) {
93+
body.metadata = parseIncidentioJsonParam(params.metadata, 'metadata', undefined)
94+
}
95+
96+
return body
97+
},
98+
},
99+
100+
transformResponse: async (response: Response) => {
101+
const data = await response.json()
102+
103+
return {
104+
success: true,
105+
output: {
106+
deduplication_key: data.deduplication_key,
107+
message: data.message,
108+
status: data.status,
109+
},
110+
}
111+
},
112+
113+
outputs: {
114+
deduplication_key: {
115+
type: 'string',
116+
description: 'The deduplication key the event was processed with',
117+
},
118+
message: {
119+
type: 'string',
120+
description: 'Human readable message giving detail about the event',
121+
},
122+
status: {
123+
type: 'string',
124+
description: 'Status of the event',
125+
},
126+
},
127+
}

0 commit comments

Comments
 (0)