chore: import upstream snapshot with attribution
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
@@ -0,0 +1,146 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomAssignConversationParams {
accessToken: string
conversationId: string
admin_id: string
assignee_id: string
body?: string
}
export interface IntercomAssignConversationV2Response {
success: boolean
output: {
conversation: any
conversationId: string
admin_assignee_id: number | null
team_assignee_id: string | null
}
}
const assignConversationBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
conversationId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the conversation to assign',
},
admin_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the admin performing the assignment',
},
assignee_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'The ID of the admin or team to assign the conversation to. Set to "0" to unassign.',
},
body: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional message to add when assigning (e.g., "Passing to the support team")',
},
},
request: {
url: (params: IntercomAssignConversationParams) =>
buildIntercomUrl(`/conversations/${params.conversationId}/parts`),
method: 'POST',
headers: (params: IntercomAssignConversationParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomAssignConversationParams) => {
const payload: any = {
message_type: 'assignment',
type: 'admin',
admin_id: params.admin_id,
assignee_id: params.assignee_id,
}
if (params.body) {
payload.body = params.body
}
return payload
},
},
} satisfies Pick<ToolConfig<IntercomAssignConversationParams, any>, 'params' | 'request'>
export const intercomAssignConversationV2Tool: ToolConfig<
IntercomAssignConversationParams,
IntercomAssignConversationV2Response
> = {
...assignConversationBase,
id: 'intercom_assign_conversation_v2',
name: 'Assign Conversation in Intercom',
description: 'Assign a conversation to an admin or team in Intercom',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'assign_conversation')
}
const data = await response.json()
return {
success: true,
output: {
conversation: data,
conversationId: data.id,
admin_assignee_id: data.admin_assignee_id ?? null,
team_assignee_id: data.team_assignee_id ?? null,
},
}
},
outputs: {
conversation: {
type: 'object',
description: 'The assigned conversation object',
properties: {
id: { type: 'string', description: 'Unique identifier for the conversation' },
type: { type: 'string', description: 'Object type (conversation)' },
state: { type: 'string', description: 'State of the conversation' },
open: { type: 'boolean', description: 'Whether the conversation is open' },
admin_assignee_id: {
type: 'number',
description: 'ID of the assigned admin',
optional: true,
},
team_assignee_id: {
type: 'string',
description: 'ID of the assigned team',
optional: true,
},
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when conversation was last updated',
},
},
},
conversationId: { type: 'string', description: 'ID of the assigned conversation' },
admin_assignee_id: {
type: 'number',
description: 'ID of the assigned admin',
optional: true,
},
team_assignee_id: { type: 'string', description: 'ID of the assigned team', optional: true },
},
}
@@ -0,0 +1,115 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomAttachContactToCompanyParams {
accessToken: string
contactId: string
companyId: string
}
export interface IntercomAttachContactToCompanyV2Response {
success: boolean
output: {
company: any
companyId: string
name: string | null
}
}
const attachContactToCompanyBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
contactId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the contact to attach to the company',
},
companyId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the company to attach the contact to',
},
},
request: {
url: (params: IntercomAttachContactToCompanyParams) =>
buildIntercomUrl(`/contacts/${params.contactId}/companies`),
method: 'POST',
headers: (params: IntercomAttachContactToCompanyParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomAttachContactToCompanyParams) => ({
id: params.companyId,
}),
},
} satisfies Pick<ToolConfig<IntercomAttachContactToCompanyParams, any>, 'params' | 'request'>
export const intercomAttachContactToCompanyV2Tool: ToolConfig<
IntercomAttachContactToCompanyParams,
IntercomAttachContactToCompanyV2Response
> = {
...attachContactToCompanyBase,
id: 'intercom_attach_contact_to_company_v2',
name: 'Attach Contact to Company in Intercom',
description: 'Attach a contact to a company in Intercom',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'attach_contact_to_company')
}
const data = await response.json()
return {
success: true,
output: {
company: {
id: data.id,
type: data.type ?? 'company',
company_id: data.company_id ?? null,
name: data.name ?? null,
created_at: data.created_at ?? null,
updated_at: data.updated_at ?? null,
user_count: data.user_count ?? null,
session_count: data.session_count ?? null,
monthly_spend: data.monthly_spend ?? null,
plan: data.plan ?? null,
},
companyId: data.id,
name: data.name ?? null,
},
}
},
outputs: {
company: {
type: 'object',
description: 'The company object the contact was attached to',
properties: {
id: { type: 'string', description: 'Unique identifier for the company' },
type: { type: 'string', description: 'Object type (company)' },
company_id: { type: 'string', description: 'The company_id you defined' },
name: { type: 'string', description: 'Name of the company' },
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
updated_at: { type: 'number', description: 'Unix timestamp when company was updated' },
user_count: { type: 'number', description: 'Number of users in the company' },
session_count: { type: 'number', description: 'Number of sessions' },
monthly_spend: { type: 'number', description: 'Monthly spend amount' },
plan: { type: 'object', description: 'Company plan details' },
},
},
companyId: { type: 'string', description: 'ID of the company' },
name: { type: 'string', description: 'Name of the company', optional: true },
},
}
@@ -0,0 +1,129 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomCloseConversationParams {
accessToken: string
conversationId: string
admin_id: string
body?: string
}
export interface IntercomCloseConversationV2Response {
success: boolean
output: {
conversation: any
conversationId: string
state: string
}
}
const closeConversationBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
conversationId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the conversation to close',
},
admin_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the admin performing the action',
},
body: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional closing message to add to the conversation',
},
},
request: {
url: (params: IntercomCloseConversationParams) =>
buildIntercomUrl(`/conversations/${params.conversationId}/parts`),
method: 'POST',
headers: (params: IntercomCloseConversationParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomCloseConversationParams) => {
const payload: any = {
message_type: 'close',
type: 'admin',
admin_id: params.admin_id,
}
if (params.body) {
payload.body = params.body
}
return payload
},
},
} satisfies Pick<ToolConfig<IntercomCloseConversationParams, any>, 'params' | 'request'>
export const intercomCloseConversationV2Tool: ToolConfig<
IntercomCloseConversationParams,
IntercomCloseConversationV2Response
> = {
...closeConversationBase,
id: 'intercom_close_conversation_v2',
name: 'Close Conversation in Intercom',
description: 'Close a conversation in Intercom',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'close_conversation')
}
const data = await response.json()
return {
success: true,
output: {
conversation: {
id: data.id,
type: data.type ?? 'conversation',
state: data.state ?? 'closed',
open: data.open ?? false,
read: data.read ?? false,
created_at: data.created_at ?? null,
updated_at: data.updated_at ?? null,
},
conversationId: data.id,
state: data.state ?? 'closed',
},
}
},
outputs: {
conversation: {
type: 'object',
description: 'The closed conversation object',
properties: {
id: { type: 'string', description: 'Unique identifier for the conversation' },
type: { type: 'string', description: 'Object type (conversation)' },
state: { type: 'string', description: 'State of the conversation (closed)' },
open: { type: 'boolean', description: 'Whether the conversation is open (false)' },
read: { type: 'boolean', description: 'Whether the conversation has been read' },
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when conversation was last updated',
},
},
},
conversationId: { type: 'string', description: 'ID of the closed conversation' },
state: { type: 'string', description: 'State of the conversation (closed)' },
},
}
+350
View File
@@ -0,0 +1,350 @@
import { createLogger } from '@sim/logger'
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('IntercomCreateCompany')
export interface IntercomCreateCompanyParams {
accessToken: string
company_id: string
name?: string
website?: string
plan?: string
size?: number
industry?: string
monthly_spend?: number
custom_attributes?: string
remote_created_at?: number
}
export interface IntercomCreateCompanyResponse {
success: boolean
output: {
company: {
id: string
type: string
app_id: string
company_id: string
name?: string
website?: string
plan: Record<string, any>
size?: number
industry?: string
monthly_spend: number
session_count: number
user_count: number
created_at: number
updated_at: number
remote_created_at?: number
custom_attributes: Record<string, any>
tags: {
type: string
tags: any[]
}
segments: {
type: string
segments: any[]
}
[key: string]: any
}
metadata: {
operation: 'create_company'
companyId: string
}
success: boolean
}
}
const createCompanyBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
company_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Your unique identifier for the company',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The name of the company',
},
website: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The company website',
},
plan: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The company plan name',
},
size: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'The number of employees in the company',
},
industry: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The industry the company operates in',
},
monthly_spend: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description:
'How much revenue the company generates for your business. Note: This field truncates floats to whole integers (e.g., 155.98 becomes 155)',
},
custom_attributes: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Custom attributes as JSON object',
},
remote_created_at: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'The time the company was created by you as a Unix timestamp',
},
},
request: {
url: () => buildIntercomUrl('/companies'),
method: 'POST',
headers: (params: IntercomCreateCompanyParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomCreateCompanyParams) => {
const company: any = {
company_id: params.company_id,
}
if (params.name) company.name = params.name
if (params.website) company.website = params.website
if (params.plan) company.plan = params.plan
if (params.size) company.size = params.size
if (params.industry) company.industry = params.industry
if (params.monthly_spend) company.monthly_spend = params.monthly_spend
if (params.custom_attributes) {
try {
company.custom_attributes = JSON.parse(params.custom_attributes)
} catch (error) {
logger.warn('Failed to parse custom attributes', { error })
}
}
if (params.remote_created_at) company.remote_created_at = params.remote_created_at
return company
},
},
} satisfies Pick<ToolConfig<IntercomCreateCompanyParams, any>, 'params' | 'request'>
export const intercomCreateCompanyTool: ToolConfig<
IntercomCreateCompanyParams,
IntercomCreateCompanyResponse
> = {
id: 'intercom_create_company',
name: 'Create Company in Intercom',
description: 'Create or update a company in Intercom',
version: '1.0.0',
...createCompanyBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'create_company')
}
const data = await response.json()
return {
success: true,
output: {
company: data,
metadata: {
operation: 'create_company' as const,
companyId: data.id,
},
success: true,
},
}
},
outputs: {
company: {
type: 'object',
description: 'Created or updated company object',
properties: {
id: { type: 'string', description: 'Unique identifier for the company' },
type: { type: 'string', description: 'Object type (company)' },
app_id: { type: 'string', description: 'Intercom app ID' },
company_id: { type: 'string', description: 'Your unique identifier for the company' },
name: { type: 'string', description: 'Name of the company' },
website: { type: 'string', description: 'Company website URL' },
plan: { type: 'object', description: 'Company plan information' },
size: { type: 'number', description: 'Number of employees' },
industry: { type: 'string', description: 'Industry the company operates in' },
monthly_spend: { type: 'number', description: 'Monthly revenue from this company' },
session_count: { type: 'number', description: 'Number of sessions' },
user_count: { type: 'number', description: 'Number of users in the company' },
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
updated_at: { type: 'number', description: 'Unix timestamp when company was last updated' },
remote_created_at: {
type: 'number',
description: 'Unix timestamp when company was created by you',
},
custom_attributes: { type: 'object', description: 'Custom attributes set on the company' },
tags: {
type: 'object',
description: 'Tags associated with the company',
properties: {
type: { type: 'string', description: 'Tag list type' },
tags: { type: 'array', description: 'Array of tag objects' },
},
},
segments: {
type: 'object',
description: 'Segments the company belongs to',
properties: {
type: { type: 'string', description: 'Segment list type' },
segments: { type: 'array', description: 'Array of segment objects' },
},
},
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (create_company)' },
companyId: { type: 'string', description: 'ID of the created/updated company' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
interface IntercomCreateCompanyV2Response {
success: boolean
output: {
company: {
id: string
type: string
app_id: string
company_id: string
name?: string
website?: string
plan: Record<string, any>
size?: number
industry?: string
monthly_spend: number
session_count: number
user_count: number
created_at: number
updated_at: number
remote_created_at?: number
custom_attributes: Record<string, any>
tags: {
type: string
tags: any[]
}
segments: {
type: string
segments: any[]
}
[key: string]: any
}
companyId: string
}
}
export const intercomCreateCompanyV2Tool: ToolConfig<
IntercomCreateCompanyParams,
IntercomCreateCompanyV2Response
> = {
...createCompanyBase,
id: 'intercom_create_company_v2',
name: 'Create Company in Intercom',
description: 'Create or update a company in Intercom',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'create_company')
}
const data = await response.json()
return {
success: true,
output: {
company: data,
companyId: data.id,
},
}
},
outputs: {
company: {
type: 'object',
description: 'Created or updated company object',
properties: {
id: { type: 'string', description: 'Unique identifier for the company' },
type: { type: 'string', description: 'Object type (company)' },
app_id: { type: 'string', description: 'Intercom app ID' },
company_id: { type: 'string', description: 'Your unique identifier for the company' },
name: { type: 'string', description: 'Name of the company' },
website: { type: 'string', description: 'Company website URL' },
plan: { type: 'object', description: 'Company plan information' },
size: { type: 'number', description: 'Number of employees' },
industry: { type: 'string', description: 'Industry the company operates in' },
monthly_spend: { type: 'number', description: 'Monthly revenue from this company' },
session_count: { type: 'number', description: 'Number of sessions' },
user_count: { type: 'number', description: 'Number of users in the company' },
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
updated_at: { type: 'number', description: 'Unix timestamp when company was last updated' },
remote_created_at: {
type: 'number',
description: 'Unix timestamp when company was created by you',
},
custom_attributes: { type: 'object', description: 'Custom attributes set on the company' },
tags: {
type: 'object',
description: 'Tags associated with the company',
properties: {
type: { type: 'string', description: 'Tag list type' },
tags: { type: 'array', description: 'Array of tag objects' },
},
},
segments: {
type: 'object',
description: 'Segments the company belongs to',
properties: {
type: { type: 'string', description: 'Segment list type' },
segments: { type: 'array', description: 'Array of segment objects' },
},
},
},
},
companyId: { type: 'string', description: 'ID of the created/updated company' },
},
}
+463
View File
@@ -0,0 +1,463 @@
import { createLogger } from '@sim/logger'
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('IntercomCreateContact')
export interface IntercomCreateContactParams {
accessToken: string
role?: 'user' | 'lead'
email?: string
external_id?: string
phone?: string
name?: string
avatar?: string
signed_up_at?: number
last_seen_at?: number
owner_id?: string
unsubscribed_from_emails?: boolean
custom_attributes?: string
company_id?: string
}
export interface IntercomCreateContactResponse {
success: boolean
output: {
contact: {
id: string
type: string
role: string
email: string | null
phone: string | null
name: string | null
avatar: string | null
owner_id: string | null
external_id: string | null
created_at: number
updated_at: number
signed_up_at: number | null
last_seen_at: number | null
workspace_id: string
custom_attributes: Record<string, any>
tags: {
type: string
url: string
data: any[]
has_more: boolean
total_count: number
}
notes: {
type: string
url: string
data: any[]
has_more: boolean
total_count: number
}
companies: {
type: string
url: string
data: any[]
has_more: boolean
total_count: number
}
location: {
type: string
city: string | null
region: string | null
country: string | null
country_code: string | null
continent_code: string | null
}
social_profiles: {
type: string
data: any[]
}
unsubscribed_from_emails: boolean
[key: string]: any
}
metadata: {
operation: 'create_contact'
contactId: string
}
success: boolean
}
}
const intercomCreateContactBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
role: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
"The role of the contact. Accepts 'user' or 'lead'. Defaults to 'lead' if not specified.",
},
email: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: "The contact's email address",
},
external_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'A unique identifier for the contact provided by the client',
},
phone: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: "The contact's phone number",
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: "The contact's name",
},
avatar: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'An avatar image URL for the contact',
},
signed_up_at: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'The time the user signed up as a Unix timestamp',
},
last_seen_at: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'The time the user was last seen as a Unix timestamp',
},
owner_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The id of an admin that has been assigned account ownership of the contact',
},
unsubscribed_from_emails: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether the contact is unsubscribed from emails',
},
custom_attributes: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Custom attributes as JSON object (e.g., {"attribute_name": "value"})',
},
company_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company ID to associate the contact with during creation',
},
},
request: {
url: () => buildIntercomUrl('/contacts'),
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params) => {
const contact: any = {}
if (params.role) contact.role = params.role
if (params.email) contact.email = params.email
if (params.external_id) contact.external_id = params.external_id
if (params.phone) contact.phone = params.phone
if (params.name) contact.name = params.name
if (params.avatar) contact.avatar = params.avatar
if (params.signed_up_at) contact.signed_up_at = params.signed_up_at
if (params.last_seen_at) contact.last_seen_at = params.last_seen_at
if (params.owner_id) contact.owner_id = params.owner_id
if (params.unsubscribed_from_emails !== undefined)
contact.unsubscribed_from_emails = params.unsubscribed_from_emails
if (params.custom_attributes) {
try {
contact.custom_attributes = JSON.parse(params.custom_attributes)
} catch (error) {
logger.warn('Failed to parse custom attributes', { error })
}
}
if (params.company_id) contact.company_id = params.company_id
return contact
},
},
} satisfies Pick<ToolConfig<IntercomCreateContactParams, any>, 'params' | 'request'>
export const intercomCreateContactTool: ToolConfig<
IntercomCreateContactParams,
IntercomCreateContactResponse
> = {
id: 'intercom_create_contact',
name: 'Create Contact in Intercom',
description: 'Create a new contact in Intercom with email, external_id, or role',
version: '1.0.0',
...intercomCreateContactBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'create_contact')
}
const data = await response.json()
return {
success: true,
output: {
contact: data,
metadata: {
operation: 'create_contact' as const,
contactId: data.id,
},
success: true,
},
}
},
outputs: {
contact: {
type: 'object',
description: 'Created contact object',
properties: {
id: { type: 'string', description: 'Unique identifier for the contact' },
type: { type: 'string', description: 'Object type (contact)' },
role: { type: 'string', description: 'Role of the contact (user or lead)' },
email: { type: 'string', description: 'Email address of the contact', optional: true },
phone: { type: 'string', description: 'Phone number of the contact', optional: true },
name: { type: 'string', description: 'Name of the contact', optional: true },
avatar: { type: 'string', description: 'Avatar URL of the contact', optional: true },
owner_id: {
type: 'string',
description: 'ID of the admin assigned to this contact',
optional: true,
},
external_id: {
type: 'string',
description: 'External identifier for the contact',
optional: true,
},
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
updated_at: { type: 'number', description: 'Unix timestamp when contact was last updated' },
signed_up_at: { type: 'number', description: 'Unix timestamp when user signed up' },
last_seen_at: { type: 'number', description: 'Unix timestamp when user was last seen' },
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
custom_attributes: { type: 'object', description: 'Custom attributes set on the contact' },
tags: {
type: 'object',
description: 'Tags associated with the contact',
properties: {
type: { type: 'string', description: 'List type' },
url: { type: 'string', description: 'URL to fetch tags' },
data: { type: 'array', description: 'Array of tag objects' },
has_more: { type: 'boolean', description: 'Whether there are more tags' },
total_count: { type: 'number', description: 'Total number of tags' },
},
},
notes: {
type: 'object',
description: 'Notes associated with the contact',
properties: {
type: { type: 'string', description: 'List type' },
url: { type: 'string', description: 'URL to fetch notes' },
data: { type: 'array', description: 'Array of note objects' },
has_more: { type: 'boolean', description: 'Whether there are more notes' },
total_count: { type: 'number', description: 'Total number of notes' },
},
},
companies: {
type: 'object',
description: 'Companies associated with the contact',
properties: {
type: { type: 'string', description: 'List type' },
url: { type: 'string', description: 'URL to fetch companies' },
data: { type: 'array', description: 'Array of company objects' },
has_more: { type: 'boolean', description: 'Whether there are more companies' },
total_count: { type: 'number', description: 'Total number of companies' },
},
},
location: {
type: 'object',
description: 'Location information for the contact',
properties: {
type: { type: 'string', description: 'Location type' },
city: { type: 'string', description: 'City' },
region: { type: 'string', description: 'Region/State' },
country: { type: 'string', description: 'Country' },
country_code: { type: 'string', description: 'Country code' },
continent_code: { type: 'string', description: 'Continent code' },
},
},
social_profiles: {
type: 'object',
description: 'Social profiles of the contact',
properties: {
type: { type: 'string', description: 'List type' },
data: { type: 'array', description: 'Array of social profile objects' },
},
},
unsubscribed_from_emails: {
type: 'boolean',
description: 'Whether contact is unsubscribed from emails',
},
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (create_contact)' },
contactId: { type: 'string', description: 'ID of the created contact' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
interface IntercomCreateContactV2Response {
success: boolean
output: {
contact: IntercomCreateContactResponse['output']['contact']
contactId: string
}
}
export const intercomCreateContactV2Tool: ToolConfig<
IntercomCreateContactParams,
IntercomCreateContactV2Response
> = {
...intercomCreateContactBase,
id: 'intercom_create_contact_v2',
name: 'Create Contact in Intercom',
description:
'Create a new contact in Intercom with email, external_id, or role. Returns API-aligned fields only.',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'create_contact')
}
const data = await response.json()
return {
success: true,
output: {
contact: data,
contactId: data.id,
},
}
},
outputs: {
contact: {
type: 'object',
description: 'Created contact object',
properties: {
id: { type: 'string', description: 'Unique identifier for the contact' },
type: { type: 'string', description: 'Object type (contact)' },
role: { type: 'string', description: 'Role of the contact (user or lead)' },
email: { type: 'string', description: 'Email address of the contact', optional: true },
phone: { type: 'string', description: 'Phone number of the contact', optional: true },
name: { type: 'string', description: 'Name of the contact', optional: true },
avatar: { type: 'string', description: 'Avatar URL of the contact', optional: true },
owner_id: {
type: 'string',
description: 'ID of the admin assigned to this contact',
optional: true,
},
external_id: {
type: 'string',
description: 'External identifier for the contact',
optional: true,
},
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
updated_at: { type: 'number', description: 'Unix timestamp when contact was last updated' },
signed_up_at: { type: 'number', description: 'Unix timestamp when user signed up' },
last_seen_at: { type: 'number', description: 'Unix timestamp when user was last seen' },
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
custom_attributes: { type: 'object', description: 'Custom attributes set on the contact' },
tags: {
type: 'object',
description: 'Tags associated with the contact',
properties: {
type: { type: 'string', description: 'List type' },
url: { type: 'string', description: 'URL to fetch tags' },
data: { type: 'array', description: 'Array of tag objects' },
has_more: { type: 'boolean', description: 'Whether there are more tags' },
total_count: { type: 'number', description: 'Total number of tags' },
},
},
notes: {
type: 'object',
description: 'Notes associated with the contact',
properties: {
type: { type: 'string', description: 'List type' },
url: { type: 'string', description: 'URL to fetch notes' },
data: { type: 'array', description: 'Array of note objects' },
has_more: { type: 'boolean', description: 'Whether there are more notes' },
total_count: { type: 'number', description: 'Total number of notes' },
},
},
companies: {
type: 'object',
description: 'Companies associated with the contact',
properties: {
type: { type: 'string', description: 'List type' },
url: { type: 'string', description: 'URL to fetch companies' },
data: { type: 'array', description: 'Array of company objects' },
has_more: { type: 'boolean', description: 'Whether there are more companies' },
total_count: { type: 'number', description: 'Total number of companies' },
},
},
location: {
type: 'object',
description: 'Location information for the contact',
properties: {
type: { type: 'string', description: 'Location type' },
city: { type: 'string', description: 'City' },
region: { type: 'string', description: 'Region/State' },
country: { type: 'string', description: 'Country' },
country_code: { type: 'string', description: 'Country code' },
continent_code: { type: 'string', description: 'Continent code' },
},
},
social_profiles: {
type: 'object',
description: 'Social profiles of the contact',
properties: {
type: { type: 'string', description: 'List type' },
data: { type: 'array', description: 'Array of social profile objects' },
},
},
unsubscribed_from_emails: {
type: 'boolean',
description: 'Whether contact is unsubscribed from emails',
},
},
},
contactId: { type: 'string', description: 'ID of the created contact' },
},
}
+148
View File
@@ -0,0 +1,148 @@
import { createLogger } from '@sim/logger'
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('IntercomCreateEvent')
export interface IntercomCreateEventParams {
accessToken: string
event_name: string
created_at?: number
user_id?: string
email?: string
id?: string
metadata?: string
}
export interface IntercomCreateEventV2Response {
success: boolean
output: {
accepted: boolean
}
}
const createEventBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
event_name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'The name of the event (e.g., "order-completed"). Use past-tense verb-noun format for readability.',
},
created_at: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description:
'Unix timestamp for when the event occurred. Strongly recommended for uniqueness.',
},
user_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Your identifier for the user (external_id)',
},
email: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Email address of the user. Use only if your app uses email to uniquely identify users.',
},
id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The Intercom contact ID',
},
metadata: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'JSON object with up to 10 metadata key-value pairs about the event (e.g., {"order_value": 99.99})',
},
},
request: {
url: () => buildIntercomUrl('/events'),
method: 'POST',
headers: (params: IntercomCreateEventParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomCreateEventParams) => {
const payload: any = {
event_name: params.event_name,
}
if (params.created_at) {
payload.created_at = params.created_at
} else {
payload.created_at = Math.floor(Date.now() / 1000)
}
if (params.user_id) {
payload.user_id = params.user_id
}
if (params.email) {
payload.email = params.email
}
if (params.id) {
payload.id = params.id
}
if (params.metadata) {
try {
payload.metadata = JSON.parse(params.metadata)
} catch (error) {
logger.warn('Failed to parse metadata, ignoring', { error })
}
}
return payload
},
},
} satisfies Pick<ToolConfig<IntercomCreateEventParams, any>, 'params' | 'request'>
export const intercomCreateEventV2Tool: ToolConfig<
IntercomCreateEventParams,
IntercomCreateEventV2Response
> = {
...createEventBase,
id: 'intercom_create_event_v2',
name: 'Create Event in Intercom',
description: 'Track a custom event for a contact in Intercom',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'create_event')
}
return {
success: true,
output: {
accepted: true,
},
}
},
outputs: {
accepted: {
type: 'boolean',
description: 'Whether the event was accepted (202 Accepted)',
},
},
}
+244
View File
@@ -0,0 +1,244 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomCreateMessageParams {
accessToken: string
message_type: 'inapp' | 'email'
template: 'plain' | 'personal'
subject?: string
body: string
from_type: string
from_id: string
to_type: string
to_id: string
created_at?: number
}
export interface IntercomCreateMessageResponse {
success: boolean
output: {
message: any
metadata: {
operation: 'create_message'
messageId: string
}
success: boolean
}
}
export interface IntercomCreateMessageV2Response {
success: boolean
output: {
message: any
messageId: string
success: boolean
}
}
const createMessageBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
message_type: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Message type: "inapp" for in-app messages or "email" for email messages',
},
template: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Message template style: "plain" for plain text or "personal" for personalized style',
},
subject: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The subject of the message (for email type)',
},
body: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The body of the message',
},
from_type: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Sender type: "admin"',
},
from_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the admin sending the message',
},
to_type: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Recipient type: "contact"',
},
to_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the contact receiving the message',
},
created_at: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description:
'Unix timestamp for when the message was created. If not provided, current time is used.',
},
},
request: {
url: () => buildIntercomUrl('/messages'),
method: 'POST',
headers: (params: IntercomCreateMessageParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomCreateMessageParams) => {
// Map "inapp" to "in_app" as required by Intercom API
const apiMessageType = params.message_type === 'inapp' ? 'in_app' : params.message_type
const message: any = {
message_type: apiMessageType,
template: params.template,
body: params.body,
from: {
type: params.from_type,
id: params.from_id,
},
to: {
type: params.to_type,
id: params.to_id,
},
}
if (params.subject && params.message_type === 'email') {
message.subject = params.subject
}
if (params.created_at) message.created_at = params.created_at
return message
},
},
} satisfies Pick<ToolConfig<IntercomCreateMessageParams, any>, 'params' | 'request'>
export const intercomCreateMessageTool: ToolConfig<
IntercomCreateMessageParams,
IntercomCreateMessageResponse
> = {
id: 'intercom_create_message',
name: 'Create Message in Intercom',
description: 'Create and send a new admin-initiated message in Intercom',
version: '1.0.0',
...createMessageBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'create_message')
}
const data = await response.json()
return {
success: true,
output: {
message: data,
metadata: {
operation: 'create_message' as const,
messageId: data.id,
},
success: true,
},
}
},
outputs: {
message: {
type: 'object',
description: 'Created message object',
properties: {
id: { type: 'string', description: 'Unique identifier for the message' },
type: { type: 'string', description: 'Object type (message)' },
created_at: { type: 'number', description: 'Unix timestamp when message was created' },
body: { type: 'string', description: 'Body of the message' },
message_type: { type: 'string', description: 'Type of the message (in_app or email)' },
conversation_id: { type: 'string', description: 'ID of the conversation created' },
owner: { type: 'object', description: 'Owner of the message' },
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (create_message)' },
messageId: { type: 'string', description: 'ID of the created message' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
export const intercomCreateMessageV2Tool: ToolConfig<
IntercomCreateMessageParams,
IntercomCreateMessageV2Response
> = {
...createMessageBase,
id: 'intercom_create_message_v2',
name: 'Create Message in Intercom',
description:
'Create and send a new admin-initiated message in Intercom. Returns API-aligned fields only.',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'create_message')
}
const data = await response.json()
return {
success: true,
output: {
message: data,
messageId: data.id,
success: true,
},
}
},
outputs: {
message: {
type: 'object',
description: 'Created message object',
properties: {
id: { type: 'string', description: 'Unique identifier for the message' },
type: { type: 'string', description: 'Object type (message)' },
created_at: { type: 'number', description: 'Unix timestamp when message was created' },
body: { type: 'string', description: 'Body of the message' },
message_type: { type: 'string', description: 'Type of the message (in_app or email)' },
conversation_id: { type: 'string', description: 'ID of the conversation created' },
owner: { type: 'object', description: 'Owner of the message' },
},
},
messageId: { type: 'string', description: 'ID of the created message' },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+131
View File
@@ -0,0 +1,131 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomCreateNoteParams {
accessToken: string
contactId: string
body: string
admin_id?: string
}
export interface IntercomCreateNoteV2Response {
success: boolean
output: {
id: string
body: string
created_at: number
type: string
author: any | null
contact: any | null
}
}
const createNoteBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
contactId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the contact to add the note to',
},
body: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The text content of the note',
},
admin_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The ID of the admin creating the note',
},
},
request: {
url: (params: IntercomCreateNoteParams) =>
buildIntercomUrl(`/contacts/${params.contactId}/notes`),
method: 'POST',
headers: (params: IntercomCreateNoteParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomCreateNoteParams) => {
const payload: any = {
body: params.body,
}
if (params.admin_id) {
payload.admin_id = params.admin_id
}
return payload
},
},
} satisfies Pick<ToolConfig<IntercomCreateNoteParams, any>, 'params' | 'request'>
export const intercomCreateNoteV2Tool: ToolConfig<
IntercomCreateNoteParams,
IntercomCreateNoteV2Response
> = {
...createNoteBase,
id: 'intercom_create_note_v2',
name: 'Create Note in Intercom',
description: 'Add a note to a specific contact',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'create_note')
}
const data = await response.json()
return {
success: true,
output: {
id: data.id,
body: data.body,
created_at: data.created_at,
type: data.type ?? 'note',
author: data.author ?? null,
contact: data.contact ?? null,
},
}
},
outputs: {
id: { type: 'string', description: 'Unique identifier for the note' },
body: { type: 'string', description: 'The text content of the note' },
created_at: { type: 'number', description: 'Unix timestamp when the note was created' },
type: { type: 'string', description: 'Object type (note)' },
author: {
type: 'object',
description: 'The admin who created the note',
optional: true,
properties: {
type: { type: 'string', description: 'Author type (admin)' },
id: { type: 'string', description: 'Author ID' },
name: { type: 'string', description: 'Author name' },
email: { type: 'string', description: 'Author email' },
},
},
contact: {
type: 'object',
description: 'The contact the note was created for',
optional: true,
properties: {
type: { type: 'string', description: 'Contact type' },
id: { type: 'string', description: 'Contact ID' },
},
},
},
}
+97
View File
@@ -0,0 +1,97 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomCreateTagParams {
accessToken: string
name: string
id?: string
}
export interface IntercomCreateTagV2Response {
success: boolean
output: {
id: string
name: string
type: string
}
}
const createTagBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'The name of the tag. Will create a new tag if not found, or update the name if id is provided.',
},
id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The ID of an existing tag to update. Omit to create a new tag.',
},
},
request: {
url: () => buildIntercomUrl('/tags'),
method: 'POST',
headers: (params: IntercomCreateTagParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomCreateTagParams) => {
const payload: any = {
name: params.name,
}
if (params.id) {
payload.id = params.id
}
return payload
},
},
} satisfies Pick<ToolConfig<IntercomCreateTagParams, any>, 'params' | 'request'>
export const intercomCreateTagV2Tool: ToolConfig<
IntercomCreateTagParams,
IntercomCreateTagV2Response
> = {
...createTagBase,
id: 'intercom_create_tag_v2',
name: 'Create Tag in Intercom',
description: 'Create a new tag or update an existing tag name',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'create_tag')
}
const data = await response.json()
return {
success: true,
output: {
id: data.id,
name: data.name,
type: data.type ?? 'tag',
},
}
},
outputs: {
id: { type: 'string', description: 'Unique identifier for the tag' },
name: { type: 'string', description: 'Name of the tag' },
type: { type: 'string', description: 'Object type (tag)' },
},
}
+262
View File
@@ -0,0 +1,262 @@
import { createLogger } from '@sim/logger'
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('IntercomCreateTicket')
export interface IntercomCreateTicketParams {
accessToken: string
ticket_type_id: string
contacts: string
ticket_attributes: string
company_id?: string
created_at?: number
conversation_to_link_id?: string
disable_notifications?: boolean
}
export interface IntercomCreateTicketResponse {
success: boolean
output: {
ticket: any
metadata: {
operation: 'create_ticket'
ticketId: string
}
success: boolean
}
}
export interface IntercomCreateTicketV2Response {
success: boolean
output: {
ticket: any
ticketId: string
success: boolean
}
}
const createTicketBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
ticket_type_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the ticket type',
},
contacts: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'JSON array of contact identifiers (e.g., [{"id": "contact_id"}])',
},
ticket_attributes: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'JSON object with ticket attributes including _default_title_ and _default_description_',
},
company_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company ID to associate the ticket with',
},
created_at: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description:
'Unix timestamp for when the ticket was created. If not provided, current time is used.',
},
conversation_to_link_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of an existing conversation to link to this ticket',
},
disable_notifications: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'When true, suppresses notifications when the ticket is created',
},
},
request: {
url: () => buildIntercomUrl('/tickets'),
method: 'POST',
headers: (params: IntercomCreateTicketParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomCreateTicketParams) => {
const ticket: any = {
ticket_type_id: params.ticket_type_id,
}
try {
ticket.contacts = JSON.parse(params.contacts)
} catch (error) {
logger.warn('Failed to parse contacts, using as single contact ID', { error })
ticket.contacts = [{ id: params.contacts }]
}
try {
ticket.ticket_attributes = JSON.parse(params.ticket_attributes)
} catch (error) {
logger.error('Failed to parse ticket attributes', { error })
throw new Error('ticket_attributes must be a valid JSON object')
}
if (params.company_id) ticket.company_id = params.company_id
if (params.created_at) ticket.created_at = params.created_at
if (params.conversation_to_link_id)
ticket.conversation_to_link_id = params.conversation_to_link_id
if (params.disable_notifications !== undefined)
ticket.disable_notifications = params.disable_notifications
return ticket
},
},
} satisfies Pick<ToolConfig<IntercomCreateTicketParams, any>, 'params' | 'request'>
export const intercomCreateTicketTool: ToolConfig<
IntercomCreateTicketParams,
IntercomCreateTicketResponse
> = {
id: 'intercom_create_ticket',
name: 'Create Ticket in Intercom',
description: 'Create a new ticket in Intercom',
version: '1.0.0',
...createTicketBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'create_ticket')
}
const data = await response.json()
return {
success: true,
output: {
ticket: data,
metadata: {
operation: 'create_ticket' as const,
ticketId: data.id,
},
success: true,
},
}
},
outputs: {
ticket: {
type: 'object',
description: 'Created ticket object',
properties: {
id: { type: 'string', description: 'Unique identifier for the ticket' },
type: { type: 'string', description: 'Object type (ticket)' },
ticket_id: { type: 'string', description: 'Ticket ID' },
ticket_type: { type: 'object', description: 'Type of the ticket', optional: true },
ticket_attributes: { type: 'object', description: 'Attributes of the ticket' },
ticket_state: { type: 'string', description: 'State of the ticket' },
ticket_state_internal_label: {
type: 'string',
description: 'Internal label for ticket state',
},
ticket_state_external_label: {
type: 'string',
description: 'External label for ticket state',
},
created_at: { type: 'number', description: 'Unix timestamp when ticket was created' },
updated_at: { type: 'number', description: 'Unix timestamp when ticket was last updated' },
contacts: { type: 'object', description: 'Contacts associated with the ticket' },
admin_assignee_id: { type: 'string', description: 'ID of assigned admin' },
team_assignee_id: { type: 'string', description: 'ID of assigned team' },
is_shared: { type: 'boolean', description: 'Whether the ticket is shared' },
open: { type: 'boolean', description: 'Whether the ticket is open' },
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (create_ticket)' },
ticketId: { type: 'string', description: 'ID of the created ticket' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
export const intercomCreateTicketV2Tool: ToolConfig<
IntercomCreateTicketParams,
IntercomCreateTicketV2Response
> = {
...createTicketBase,
id: 'intercom_create_ticket_v2',
name: 'Create Ticket in Intercom',
description: 'Create a new ticket in Intercom. Returns API-aligned fields only.',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'create_ticket')
}
const data = await response.json()
return {
success: true,
output: {
ticket: data,
ticketId: data.id,
success: true,
},
}
},
outputs: {
ticket: {
type: 'object',
description: 'Created ticket object',
properties: {
id: { type: 'string', description: 'Unique identifier for the ticket' },
type: { type: 'string', description: 'Object type (ticket)' },
ticket_id: { type: 'string', description: 'Ticket ID' },
ticket_type: { type: 'object', description: 'Type of the ticket', optional: true },
ticket_attributes: { type: 'object', description: 'Attributes of the ticket' },
ticket_state: { type: 'string', description: 'State of the ticket' },
ticket_state_internal_label: {
type: 'string',
description: 'Internal label for ticket state',
},
ticket_state_external_label: {
type: 'string',
description: 'External label for ticket state',
},
created_at: { type: 'number', description: 'Unix timestamp when ticket was created' },
updated_at: { type: 'number', description: 'Unix timestamp when ticket was last updated' },
contacts: { type: 'object', description: 'Contacts associated with the ticket' },
admin_assignee_id: { type: 'string', description: 'ID of assigned admin' },
team_assignee_id: { type: 'string', description: 'ID of assigned team' },
is_shared: { type: 'boolean', description: 'Whether the ticket is shared' },
open: { type: 'boolean', description: 'Whether the ticket is open' },
},
},
ticketId: { type: 'string', description: 'ID of the created ticket' },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+133
View File
@@ -0,0 +1,133 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomDeleteContactParams {
accessToken: string
contactId: string
}
export interface IntercomDeleteContactResponse {
success: boolean
output: {
id: string
deleted: boolean
metadata: {
operation: 'delete_contact'
}
success: boolean
}
}
const intercomDeleteContactBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
contactId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Contact ID to delete',
},
},
request: {
url: (params: IntercomDeleteContactParams) => buildIntercomUrl(`/contacts/${params.contactId}`),
method: 'DELETE',
headers: (params: IntercomDeleteContactParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
},
} satisfies Pick<ToolConfig<IntercomDeleteContactParams, any>, 'params' | 'request'>
export const intercomDeleteContactTool: ToolConfig<
IntercomDeleteContactParams,
IntercomDeleteContactResponse
> = {
id: 'intercom_delete_contact',
name: 'Delete Contact from Intercom',
description: 'Delete a contact from Intercom by ID',
version: '1.0.0',
...intercomDeleteContactBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'delete_contact')
}
const data = await response.json()
return {
success: true,
output: {
id: data.id,
deleted: true,
metadata: {
operation: 'delete_contact' as const,
},
success: true,
},
}
},
outputs: {
id: { type: 'string', description: 'ID of deleted contact' },
deleted: { type: 'boolean', description: 'Whether the contact was deleted' },
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (delete_contact)' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
interface IntercomDeleteContactV2Response {
success: boolean
output: {
id: string
deleted: boolean
}
}
export const intercomDeleteContactV2Tool: ToolConfig<
IntercomDeleteContactParams,
IntercomDeleteContactV2Response
> = {
...intercomDeleteContactBase,
id: 'intercom_delete_contact_v2',
name: 'Delete Contact from Intercom',
description: 'Delete a contact from Intercom by ID. Returns API-aligned fields only.',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'delete_contact')
}
const data = await response.json()
return {
success: true,
output: {
id: data.id,
deleted: true,
},
}
},
outputs: {
id: { type: 'string', description: 'ID of deleted contact' },
deleted: { type: 'boolean', description: 'Whether the contact was deleted' },
},
}
@@ -0,0 +1,101 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomDetachContactFromCompanyParams {
accessToken: string
contactId: string
companyId: string
}
export interface IntercomDetachContactFromCompanyV2Response {
success: boolean
output: {
company: any
companyId: string
name: string | null
}
}
const detachContactFromCompanyBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
contactId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the contact to detach from the company',
},
companyId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the company to detach the contact from',
},
},
request: {
url: (params: IntercomDetachContactFromCompanyParams) =>
buildIntercomUrl(`/contacts/${params.contactId}/companies/${params.companyId}`),
method: 'DELETE',
headers: (params: IntercomDetachContactFromCompanyParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
},
} satisfies Pick<ToolConfig<IntercomDetachContactFromCompanyParams, any>, 'params' | 'request'>
export const intercomDetachContactFromCompanyV2Tool: ToolConfig<
IntercomDetachContactFromCompanyParams,
IntercomDetachContactFromCompanyV2Response
> = {
...detachContactFromCompanyBase,
id: 'intercom_detach_contact_from_company_v2',
name: 'Detach Contact from Company in Intercom',
description: 'Remove a contact from a company in Intercom',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'detach_contact_from_company')
}
const data = await response.json()
return {
success: true,
output: {
company: {
id: data.id,
type: data.type ?? 'company',
company_id: data.company_id ?? null,
name: data.name ?? null,
},
companyId: data.id,
name: data.name ?? null,
},
}
},
outputs: {
company: {
type: 'object',
description: 'The company object the contact was detached from',
properties: {
id: { type: 'string', description: 'Unique identifier for the company' },
type: { type: 'string', description: 'Object type (company)' },
company_id: { type: 'string', description: 'The company_id you defined' },
name: { type: 'string', description: 'Name of the company' },
},
},
companyId: { type: 'string', description: 'ID of the company' },
name: { type: 'string', description: 'Name of the company', optional: true },
},
}
+172
View File
@@ -0,0 +1,172 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomGetCompanyParams {
accessToken: string
companyId: string
}
export interface IntercomGetCompanyResponse {
success: boolean
output: {
company: any
metadata: {
operation: 'get_company'
}
success: boolean
}
}
const getCompanyBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
companyId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Company ID to retrieve',
},
},
request: {
url: (params: IntercomGetCompanyParams) => buildIntercomUrl(`/companies/${params.companyId}`),
method: 'GET',
headers: (params: IntercomGetCompanyParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
},
} satisfies Pick<ToolConfig<IntercomGetCompanyParams, any>, 'params' | 'request'>
export const intercomGetCompanyTool: ToolConfig<
IntercomGetCompanyParams,
IntercomGetCompanyResponse
> = {
id: 'intercom_get_company',
name: 'Get Company from Intercom',
description: 'Retrieve a single company by ID from Intercom',
version: '1.0.0',
...getCompanyBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'get_company')
}
const data = await response.json()
return {
success: true,
output: {
company: data,
metadata: {
operation: 'get_company' as const,
},
success: true,
},
}
},
outputs: {
company: {
type: 'object',
description: 'Company object',
properties: {
id: { type: 'string', description: 'Unique identifier for the company' },
type: { type: 'string', description: 'Object type (company)' },
app_id: { type: 'string', description: 'Intercom app ID' },
company_id: { type: 'string', description: 'Your unique identifier for the company' },
name: { type: 'string', description: 'Name of the company' },
website: { type: 'string', description: 'Company website URL' },
plan: { type: 'object', description: 'Company plan information' },
size: { type: 'number', description: 'Number of employees' },
industry: { type: 'string', description: 'Industry the company operates in' },
monthly_spend: { type: 'number', description: 'Monthly revenue from this company' },
session_count: { type: 'number', description: 'Number of sessions' },
user_count: { type: 'number', description: 'Number of users in the company' },
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
updated_at: { type: 'number', description: 'Unix timestamp when company was last updated' },
custom_attributes: { type: 'object', description: 'Custom attributes set on the company' },
tags: { type: 'object', description: 'Tags associated with the company' },
segments: { type: 'object', description: 'Segments the company belongs to' },
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (get_company)' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
interface IntercomGetCompanyV2Response {
success: boolean
output: {
company: any
}
}
export const intercomGetCompanyV2Tool: ToolConfig<
IntercomGetCompanyParams,
IntercomGetCompanyV2Response
> = {
...getCompanyBase,
id: 'intercom_get_company_v2',
name: 'Get Company from Intercom',
description: 'Retrieve a single company by ID from Intercom',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'get_company')
}
const data = await response.json()
return {
success: true,
output: {
company: data,
},
}
},
outputs: {
company: {
type: 'object',
description: 'Company object',
properties: {
id: { type: 'string', description: 'Unique identifier for the company' },
type: { type: 'string', description: 'Object type (company)' },
app_id: { type: 'string', description: 'Intercom app ID' },
company_id: { type: 'string', description: 'Your unique identifier for the company' },
name: { type: 'string', description: 'Name of the company' },
website: { type: 'string', description: 'Company website URL' },
plan: { type: 'object', description: 'Company plan information' },
size: { type: 'number', description: 'Number of employees' },
industry: { type: 'string', description: 'Industry the company operates in' },
monthly_spend: { type: 'number', description: 'Monthly revenue from this company' },
session_count: { type: 'number', description: 'Number of sessions' },
user_count: { type: 'number', description: 'Number of users in the company' },
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
updated_at: { type: 'number', description: 'Unix timestamp when company was last updated' },
custom_attributes: { type: 'object', description: 'Custom attributes set on the company' },
tags: { type: 'object', description: 'Tags associated with the company' },
segments: { type: 'object', description: 'Segments the company belongs to' },
},
},
},
}
+140
View File
@@ -0,0 +1,140 @@
import {
buildIntercomUrl,
handleIntercomError,
INTERCOM_CONTACT_OUTPUT_PROPERTIES,
} from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomGetContactParams {
accessToken: string
contactId: string
}
export interface IntercomGetContactResponse {
success: boolean
output: {
contact: any
metadata: {
operation: 'get_contact'
}
success: boolean
}
}
const intercomGetContactBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
contactId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Contact ID to retrieve',
},
},
request: {
url: (params: IntercomGetContactParams) => buildIntercomUrl(`/contacts/${params.contactId}`),
method: 'GET',
headers: (params: IntercomGetContactParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
},
} satisfies Pick<ToolConfig<IntercomGetContactParams, any>, 'params' | 'request'>
export const intercomGetContactTool: ToolConfig<
IntercomGetContactParams,
IntercomGetContactResponse
> = {
id: 'intercom_get_contact',
name: 'Get Single Contact from Intercom',
description: 'Get a single contact by ID from Intercom',
version: '1.0.0',
...intercomGetContactBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'get_contact')
}
const data = await response.json()
return {
success: true,
output: {
contact: data,
metadata: {
operation: 'get_contact' as const,
},
success: true,
},
}
},
outputs: {
contact: {
type: 'object',
description: 'Contact object',
properties: INTERCOM_CONTACT_OUTPUT_PROPERTIES,
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (get_contact)' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
interface IntercomGetContactV2Response {
success: boolean
output: {
contact: any
}
}
export const intercomGetContactV2Tool: ToolConfig<
IntercomGetContactParams,
IntercomGetContactV2Response
> = {
...intercomGetContactBase,
id: 'intercom_get_contact_v2',
name: 'Get Single Contact from Intercom',
description: 'Get a single contact by ID from Intercom. Returns API-aligned fields only.',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'get_contact')
}
const data = await response.json()
return {
success: true,
output: {
contact: data,
},
}
},
outputs: {
contact: {
type: 'object',
description: 'Contact object',
properties: INTERCOM_CONTACT_OUTPUT_PROPERTIES,
},
},
}
+225
View File
@@ -0,0 +1,225 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomGetConversationParams {
accessToken: string
conversationId: string
display_as?: string
include_translations?: boolean
}
export interface IntercomGetConversationResponse {
success: boolean
output: {
conversation: any
metadata: {
operation: 'get_conversation'
}
success: boolean
}
}
const getConversationBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
conversationId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Conversation ID to retrieve',
},
display_as: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Set to "plaintext" to retrieve messages in plain text',
},
include_translations: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description:
'When true, conversation parts will be translated to the detected language of the conversation',
},
},
request: {
url: (params: IntercomGetConversationParams) => {
const url = buildIntercomUrl(`/conversations/${params.conversationId}`)
const queryParams = new URLSearchParams()
if (params.display_as) queryParams.append('display_as', params.display_as)
if (params.include_translations !== undefined)
queryParams.append('include_translations', String(params.include_translations))
const queryString = queryParams.toString()
return queryString ? `${url}?${queryString}` : url
},
method: 'GET',
headers: (params: IntercomGetConversationParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
},
} satisfies Pick<ToolConfig<IntercomGetConversationParams, any>, 'params' | 'request'>
export const intercomGetConversationTool: ToolConfig<
IntercomGetConversationParams,
IntercomGetConversationResponse
> = {
id: 'intercom_get_conversation',
name: 'Get Conversation from Intercom',
description: 'Retrieve a single conversation by ID from Intercom',
version: '1.0.0',
...getConversationBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'get_conversation')
}
const data = await response.json()
return {
success: true,
output: {
conversation: data,
metadata: {
operation: 'get_conversation' as const,
},
success: true,
},
}
},
outputs: {
conversation: {
type: 'object',
description: 'Conversation object',
properties: {
id: { type: 'string', description: 'Unique identifier for the conversation' },
type: { type: 'string', description: 'Object type (conversation)' },
title: { type: 'string', description: 'Title of the conversation', optional: true },
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when conversation was last updated',
},
waiting_since: {
type: 'number',
description: 'Unix timestamp when waiting for reply',
optional: true,
},
snoozed_until: {
type: 'number',
description: 'Unix timestamp when snooze ends',
optional: true,
},
open: { type: 'boolean', description: 'Whether the conversation is open' },
state: { type: 'string', description: 'State of the conversation' },
read: { type: 'boolean', description: 'Whether the conversation has been read' },
priority: { type: 'string', description: 'Priority of the conversation' },
admin_assignee_id: { type: 'number', description: 'ID of assigned admin', optional: true },
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
tags: { type: 'object', description: 'Tags on the conversation' },
source: { type: 'object', description: 'Source of the conversation' },
contacts: { type: 'object', description: 'Contacts in the conversation' },
teammates: { type: 'object', description: 'Teammates in the conversation' },
conversation_parts: { type: 'object', description: 'Parts of the conversation' },
statistics: { type: 'object', description: 'Conversation statistics' },
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (get_conversation)' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
interface IntercomGetConversationV2Response {
success: boolean
output: {
conversation: any
success: boolean
}
}
export const intercomGetConversationV2Tool: ToolConfig<
IntercomGetConversationParams,
IntercomGetConversationV2Response
> = {
...getConversationBase,
id: 'intercom_get_conversation_v2',
name: 'Get Conversation from Intercom',
description: 'Retrieve a single conversation by ID from Intercom',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'get_conversation')
}
const data = await response.json()
return {
success: true,
output: {
conversation: data,
success: true,
},
}
},
outputs: {
conversation: {
type: 'object',
description: 'Conversation object',
properties: {
id: { type: 'string', description: 'Unique identifier for the conversation' },
type: { type: 'string', description: 'Object type (conversation)' },
title: { type: 'string', description: 'Title of the conversation', optional: true },
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when conversation was last updated',
},
waiting_since: {
type: 'number',
description: 'Unix timestamp when waiting for reply',
optional: true,
},
snoozed_until: {
type: 'number',
description: 'Unix timestamp when snooze ends',
optional: true,
},
open: { type: 'boolean', description: 'Whether the conversation is open' },
state: { type: 'string', description: 'State of the conversation' },
read: { type: 'boolean', description: 'Whether the conversation has been read' },
priority: { type: 'string', description: 'Priority of the conversation' },
admin_assignee_id: { type: 'number', description: 'ID of assigned admin', optional: true },
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
tags: { type: 'object', description: 'Tags on the conversation' },
source: { type: 'object', description: 'Source of the conversation' },
contacts: { type: 'object', description: 'Contacts in the conversation' },
teammates: { type: 'object', description: 'Teammates in the conversation' },
conversation_parts: { type: 'object', description: 'Parts of the conversation' },
statistics: { type: 'object', description: 'Conversation statistics' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
+189
View File
@@ -0,0 +1,189 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomGetTicketParams {
accessToken: string
ticketId: string
}
export interface IntercomGetTicketResponse {
success: boolean
output: {
ticket: any
metadata: {
operation: 'get_ticket'
}
success: boolean
}
}
export interface IntercomGetTicketV2Response {
success: boolean
output: {
ticket: any
ticketId: string
success: boolean
}
}
const getTicketBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
ticketId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Ticket ID to retrieve',
},
},
request: {
url: (params: IntercomGetTicketParams) => buildIntercomUrl(`/tickets/${params.ticketId}`),
method: 'GET',
headers: (params: IntercomGetTicketParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
},
} satisfies Pick<ToolConfig<IntercomGetTicketParams, any>, 'params' | 'request'>
export const intercomGetTicketTool: ToolConfig<IntercomGetTicketParams, IntercomGetTicketResponse> =
{
id: 'intercom_get_ticket',
name: 'Get Ticket from Intercom',
description: 'Retrieve a single ticket by ID from Intercom',
version: '1.0.0',
...getTicketBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'get_ticket')
}
const data = await response.json()
return {
success: true,
output: {
ticket: data,
metadata: {
operation: 'get_ticket' as const,
},
success: true,
},
}
},
outputs: {
ticket: {
type: 'object',
description: 'Ticket object',
properties: {
id: { type: 'string', description: 'Unique identifier for the ticket' },
type: { type: 'string', description: 'Object type (ticket)' },
ticket_id: { type: 'string', description: 'Ticket ID' },
ticket_type: { type: 'object', description: 'Type of the ticket', optional: true },
ticket_attributes: { type: 'object', description: 'Attributes of the ticket' },
ticket_state: { type: 'string', description: 'State of the ticket' },
ticket_state_internal_label: {
type: 'string',
description: 'Internal label for ticket state',
},
ticket_state_external_label: {
type: 'string',
description: 'External label for ticket state',
},
created_at: { type: 'number', description: 'Unix timestamp when ticket was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when ticket was last updated',
},
contacts: { type: 'object', description: 'Contacts associated with the ticket' },
admin_assignee_id: { type: 'string', description: 'ID of assigned admin' },
team_assignee_id: { type: 'string', description: 'ID of assigned team' },
is_shared: { type: 'boolean', description: 'Whether the ticket is shared' },
open: { type: 'boolean', description: 'Whether the ticket is open' },
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (get_ticket)' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
export const intercomGetTicketV2Tool: ToolConfig<
IntercomGetTicketParams,
IntercomGetTicketV2Response
> = {
...getTicketBase,
id: 'intercom_get_ticket_v2',
name: 'Get Ticket from Intercom',
description: 'Retrieve a single ticket by ID from Intercom. Returns API-aligned fields only.',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'get_ticket')
}
const data = await response.json()
return {
success: true,
output: {
ticket: data,
ticketId: data.id,
success: true,
},
}
},
outputs: {
ticket: {
type: 'object',
description: 'Ticket object',
properties: {
id: { type: 'string', description: 'Unique identifier for the ticket' },
type: { type: 'string', description: 'Object type (ticket)' },
ticket_id: { type: 'string', description: 'Ticket ID' },
ticket_type: { type: 'object', description: 'Type of the ticket', optional: true },
ticket_attributes: { type: 'object', description: 'Attributes of the ticket' },
ticket_state: { type: 'string', description: 'State of the ticket' },
ticket_state_internal_label: {
type: 'string',
description: 'Internal label for ticket state',
},
ticket_state_external_label: {
type: 'string',
description: 'External label for ticket state',
},
created_at: { type: 'number', description: 'Unix timestamp when ticket was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when ticket was last updated',
},
contacts: { type: 'object', description: 'Contacts associated with the ticket' },
admin_assignee_id: { type: 'string', description: 'ID of assigned admin' },
team_assignee_id: { type: 'string', description: 'ID of assigned team' },
is_shared: { type: 'boolean', description: 'Whether the ticket is shared' },
open: { type: 'boolean', description: 'Whether the ticket is open' },
},
},
ticketId: { type: 'string', description: 'ID of the retrieved ticket' },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+40
View File
@@ -0,0 +1,40 @@
export { intercomAssignConversationV2Tool } from './assign_conversation'
export { intercomAttachContactToCompanyV2Tool } from './attach_contact_to_company'
export { intercomCloseConversationV2Tool } from './close_conversation'
export { intercomCreateCompanyTool, intercomCreateCompanyV2Tool } from './create_company'
export { intercomCreateContactTool, intercomCreateContactV2Tool } from './create_contact'
export { intercomCreateEventV2Tool } from './create_event'
export { intercomCreateMessageTool, intercomCreateMessageV2Tool } from './create_message'
export { intercomCreateNoteV2Tool } from './create_note'
export { intercomCreateTagV2Tool } from './create_tag'
export { intercomCreateTicketTool, intercomCreateTicketV2Tool } from './create_ticket'
export { intercomDeleteContactTool, intercomDeleteContactV2Tool } from './delete_contact'
export { intercomDetachContactFromCompanyV2Tool } from './detach_contact_from_company'
export { intercomGetCompanyTool, intercomGetCompanyV2Tool } from './get_company'
export { intercomGetContactTool, intercomGetContactV2Tool } from './get_contact'
export { intercomGetConversationTool, intercomGetConversationV2Tool } from './get_conversation'
export { intercomGetTicketTool, intercomGetTicketV2Tool } from './get_ticket'
export { intercomListAdminsV2Tool } from './list_admins'
export { intercomListCompaniesTool, intercomListCompaniesV2Tool } from './list_companies'
export { intercomListContactsTool, intercomListContactsV2Tool } from './list_contacts'
export {
intercomListConversationsTool,
intercomListConversationsV2Tool,
} from './list_conversations'
export { intercomListTagsV2Tool } from './list_tags'
export { intercomOpenConversationV2Tool } from './open_conversation'
export {
intercomReplyConversationTool,
intercomReplyConversationV2Tool,
} from './reply_conversation'
export { intercomSearchContactsTool, intercomSearchContactsV2Tool } from './search_contacts'
export {
intercomSearchConversationsTool,
intercomSearchConversationsV2Tool,
} from './search_conversations'
export { intercomSnoozeConversationV2Tool } from './snooze_conversation'
export { intercomTagContactV2Tool } from './tag_contact'
export { intercomTagConversationV2Tool } from './tag_conversation'
export { intercomUntagContactV2Tool } from './untag_contact'
export { intercomUpdateContactTool, intercomUpdateContactV2Tool } from './update_contact'
export { intercomUpdateTicketV2Tool } from './update_ticket'
+125
View File
@@ -0,0 +1,125 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomListAdminsParams {
accessToken: string
}
interface IntercomAdmin {
type: string
id: string
name: string
email: string
job_title: string | null
away_mode_enabled: boolean
away_mode_reassign: boolean
has_inbox_seat: boolean
team_ids: number[]
avatar: {
type: string
image_url: string | null
} | null
email_verified: boolean | null
}
export interface IntercomListAdminsV2Response {
success: boolean
output: {
admins: IntercomAdmin[]
type: string
}
}
const listAdminsBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
},
request: {
url: () => buildIntercomUrl('/admins'),
method: 'GET',
headers: (params: IntercomListAdminsParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
},
} satisfies Pick<ToolConfig<IntercomListAdminsParams, any>, 'params' | 'request'>
export const intercomListAdminsV2Tool: ToolConfig<
IntercomListAdminsParams,
IntercomListAdminsV2Response
> = {
...listAdminsBase,
id: 'intercom_list_admins_v2',
name: 'List Admins from Intercom',
description: 'Fetch a list of all admins for the workspace',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'list_admins')
}
const data = await response.json()
return {
success: true,
output: {
admins: data.admins ?? [],
type: data.type ?? 'admin.list',
},
}
},
outputs: {
admins: {
type: 'array',
description: 'Array of admin objects',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the admin' },
type: { type: 'string', description: 'Object type (admin)' },
name: { type: 'string', description: 'Name of the admin' },
email: { type: 'string', description: 'Email of the admin' },
job_title: { type: 'string', description: 'Job title of the admin', optional: true },
away_mode_enabled: {
type: 'boolean',
description: 'Whether admin is in away mode',
},
away_mode_reassign: {
type: 'boolean',
description: 'Whether to reassign conversations when away',
},
has_inbox_seat: {
type: 'boolean',
description: 'Whether admin has a paid inbox seat',
},
team_ids: {
type: 'array',
description: 'List of team IDs the admin belongs to',
},
avatar: {
type: 'object',
description: 'Avatar information',
optional: true,
},
email_verified: {
type: 'boolean',
description: 'Whether email is verified',
optional: true,
},
},
},
},
type: { type: 'string', description: 'Object type (admin.list)' },
},
}
+244
View File
@@ -0,0 +1,244 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomListCompaniesParams {
accessToken: string
per_page?: number
page?: number
starting_after?: string
}
export interface IntercomListCompaniesResponse {
success: boolean
output: {
companies: any[]
pages?: any
metadata: {
operation: 'list_companies'
total_count?: number
}
success: boolean
}
}
const listCompaniesBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
per_page: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page',
},
page: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Page number',
},
starting_after: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor for pagination (preferred over page-based pagination)',
},
},
request: {
url: (params: IntercomListCompaniesParams) => {
const url = buildIntercomUrl('/companies/list')
const queryParams = new URLSearchParams()
if (params.per_page) queryParams.append('per_page', params.per_page.toString())
if (params.page) queryParams.append('page', params.page.toString())
if (params.starting_after) queryParams.append('starting_after', params.starting_after)
const queryString = queryParams.toString()
return queryString ? `${url}?${queryString}` : url
},
method: 'POST',
headers: (params: IntercomListCompaniesParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
},
} satisfies Pick<ToolConfig<IntercomListCompaniesParams, any>, 'params' | 'request'>
export const intercomListCompaniesTool: ToolConfig<
IntercomListCompaniesParams,
IntercomListCompaniesResponse
> = {
id: 'intercom_list_companies',
name: 'List Companies from Intercom',
description:
'List all companies from Intercom with pagination support. Note: This endpoint has a limit of 10,000 companies that can be returned using pagination. For datasets larger than 10,000 companies, use the Scroll API instead.',
version: '1.0.0',
...listCompaniesBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'list_companies')
}
const data = await response.json()
return {
success: true,
output: {
companies: data.data || data.companies || [],
pages: data.pages,
metadata: {
operation: 'list_companies' as const,
total_count: data.total_count,
},
success: true,
},
}
},
outputs: {
companies: {
type: 'array',
description: 'Array of company objects',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the company' },
type: { type: 'string', description: 'Object type (company)' },
app_id: { type: 'string', description: 'Intercom app ID' },
company_id: { type: 'string', description: 'Your unique identifier for the company' },
name: { type: 'string', description: 'Name of the company' },
website: { type: 'string', description: 'Company website URL' },
plan: { type: 'object', description: 'Company plan information' },
monthly_spend: { type: 'number', description: 'Monthly revenue from this company' },
session_count: { type: 'number', description: 'Number of sessions' },
user_count: { type: 'number', description: 'Number of users in the company' },
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when company was last updated',
},
custom_attributes: {
type: 'object',
description: 'Custom attributes set on the company',
},
tags: { type: 'object', description: 'Tags associated with the company' },
segments: { type: 'object', description: 'Segments the company belongs to' },
},
},
},
pages: {
type: 'object',
description: 'Pagination information',
properties: {
type: { type: 'string', description: 'Pages type identifier' },
page: { type: 'number', description: 'Current page number' },
per_page: { type: 'number', description: 'Number of results per page' },
total_pages: { type: 'number', description: 'Total number of pages' },
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (list_companies)' },
total_count: { type: 'number', description: 'Total number of companies' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
interface IntercomListCompaniesV2Response {
success: boolean
output: {
companies: any[]
pages?: any
total_count?: number
success: boolean
}
}
export const intercomListCompaniesV2Tool: ToolConfig<
IntercomListCompaniesParams,
IntercomListCompaniesV2Response
> = {
...listCompaniesBase,
id: 'intercom_list_companies_v2',
name: 'List Companies from Intercom',
description:
'List all companies from Intercom with pagination support. Note: This endpoint has a limit of 10,000 companies that can be returned using pagination. For datasets larger than 10,000 companies, use the Scroll API instead.',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'list_companies')
}
const data = await response.json()
return {
success: true,
output: {
companies: data.data || data.companies || [],
pages: data.pages,
total_count: data.total_count,
success: true,
},
}
},
outputs: {
companies: {
type: 'array',
description: 'Array of company objects',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the company' },
type: { type: 'string', description: 'Object type (company)' },
app_id: { type: 'string', description: 'Intercom app ID' },
company_id: { type: 'string', description: 'Your unique identifier for the company' },
name: { type: 'string', description: 'Name of the company' },
website: { type: 'string', description: 'Company website URL' },
plan: { type: 'object', description: 'Company plan information' },
monthly_spend: { type: 'number', description: 'Monthly revenue from this company' },
session_count: { type: 'number', description: 'Number of sessions' },
user_count: { type: 'number', description: 'Number of users in the company' },
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when company was last updated',
},
custom_attributes: {
type: 'object',
description: 'Custom attributes set on the company',
},
tags: { type: 'object', description: 'Tags associated with the company' },
segments: { type: 'object', description: 'Segments the company belongs to' },
},
},
},
pages: {
type: 'object',
description: 'Pagination information',
properties: {
type: { type: 'string', description: 'Pages type identifier' },
page: { type: 'number', description: 'Current page number' },
per_page: { type: 'number', description: 'Number of results per page' },
total_pages: { type: 'number', description: 'Total number of pages' },
},
},
total_count: { type: 'number', description: 'Total number of companies' },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+234
View File
@@ -0,0 +1,234 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomListContactsParams {
accessToken: string
per_page?: number
starting_after?: string
}
export interface IntercomListContactsResponse {
success: boolean
output: {
contacts: any[]
pages?: any
metadata: {
operation: 'list_contacts'
total_count?: number
}
success: boolean
}
}
const listContactsBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
per_page: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page (max: 150)',
},
starting_after: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor for pagination - ID to start after',
},
},
request: {
url: (params: IntercomListContactsParams) => {
const url = buildIntercomUrl('/contacts')
const queryParams = new URLSearchParams()
if (params.per_page) queryParams.append('per_page', params.per_page.toString())
if (params.starting_after) queryParams.append('starting_after', params.starting_after)
const queryString = queryParams.toString()
return queryString ? `${url}?${queryString}` : url
},
method: 'GET',
headers: (params: IntercomListContactsParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
},
} satisfies Pick<ToolConfig<IntercomListContactsParams, any>, 'params' | 'request'>
export const intercomListContactsTool: ToolConfig<
IntercomListContactsParams,
IntercomListContactsResponse
> = {
id: 'intercom_list_contacts',
name: 'List Contacts from Intercom',
description: 'List all contacts from Intercom with pagination support',
version: '1.0.0',
...listContactsBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'list_contacts')
}
const data = await response.json()
return {
success: true,
output: {
contacts: data.data || [],
pages: data.pages,
metadata: {
operation: 'list_contacts' as const,
total_count: data.total_count,
},
success: true,
},
}
},
outputs: {
contacts: {
type: 'array',
description: 'Array of contact objects',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the contact' },
type: { type: 'string', description: 'Object type (contact)' },
role: { type: 'string', description: 'Role of the contact (user or lead)' },
email: { type: 'string', description: 'Email address of the contact' },
phone: { type: 'string', description: 'Phone number of the contact' },
name: { type: 'string', description: 'Name of the contact' },
external_id: { type: 'string', description: 'External identifier for the contact' },
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when contact was last updated',
},
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
custom_attributes: {
type: 'object',
description: 'Custom attributes set on the contact',
},
tags: { type: 'object', description: 'Tags associated with the contact' },
companies: { type: 'object', description: 'Companies associated with the contact' },
},
},
},
pages: {
type: 'object',
description: 'Pagination information',
properties: {
type: { type: 'string', description: 'Pages type identifier' },
page: { type: 'number', description: 'Current page number' },
per_page: { type: 'number', description: 'Number of results per page' },
total_pages: { type: 'number', description: 'Total number of pages' },
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (list_contacts)' },
total_count: { type: 'number', description: 'Total number of contacts' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
interface IntercomListContactsV2Response {
success: boolean
output: {
contacts: any[]
pages?: any
total_count?: number
}
}
export const intercomListContactsV2Tool: ToolConfig<
IntercomListContactsParams,
IntercomListContactsV2Response
> = {
...listContactsBase,
id: 'intercom_list_contacts_v2',
name: 'List Contacts from Intercom',
description: 'List all contacts from Intercom with pagination support',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'list_contacts')
}
const data = await response.json()
return {
success: true,
output: {
contacts: data.data ?? null,
pages: data.pages ?? null,
total_count: data.total_count ?? null,
},
}
},
outputs: {
contacts: {
type: 'array',
description: 'Array of contact objects',
optional: true,
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the contact' },
type: { type: 'string', description: 'Object type (contact)' },
role: { type: 'string', description: 'Role of the contact (user or lead)' },
email: { type: 'string', description: 'Email address of the contact', optional: true },
phone: { type: 'string', description: 'Phone number of the contact', optional: true },
name: { type: 'string', description: 'Name of the contact', optional: true },
external_id: {
type: 'string',
description: 'External identifier for the contact',
optional: true,
},
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when contact was last updated',
},
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
custom_attributes: {
type: 'object',
description: 'Custom attributes set on the contact',
},
tags: { type: 'object', description: 'Tags associated with the contact', optional: true },
companies: { type: 'object', description: 'Companies associated with the contact' },
},
},
},
pages: {
type: 'object',
description: 'Pagination information',
optional: true,
properties: {
type: { type: 'string', description: 'Pages type identifier' },
page: { type: 'number', description: 'Current page number' },
per_page: { type: 'number', description: 'Number of results per page' },
total_pages: { type: 'number', description: 'Total number of pages' },
},
},
total_count: { type: 'number', description: 'Total number of contacts', optional: true },
},
}
@@ -0,0 +1,260 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomListConversationsParams {
accessToken: string
per_page?: number
starting_after?: string
sort?: string
order?: 'asc' | 'desc'
}
export interface IntercomListConversationsResponse {
success: boolean
output: {
conversations: any[]
pages?: any
metadata: {
operation: 'list_conversations'
total_count?: number
}
success: boolean
}
}
const listConversationsBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
per_page: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page (max: 150)',
},
starting_after: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor for pagination',
},
sort: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Field to sort by (e.g., "waiting_since", "updated_at", "created_at")',
},
order: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Sort order: "asc" (ascending) or "desc" (descending)',
},
},
request: {
url: (params: IntercomListConversationsParams) => {
const url = buildIntercomUrl('/conversations')
const queryParams = new URLSearchParams()
if (params.per_page) queryParams.append('per_page', params.per_page.toString())
if (params.starting_after) queryParams.append('starting_after', params.starting_after)
if (params.sort) queryParams.append('sort', params.sort)
if (params.order) queryParams.append('order', params.order)
const queryString = queryParams.toString()
return queryString ? `${url}?${queryString}` : url
},
method: 'GET',
headers: (params: IntercomListConversationsParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
},
} satisfies Pick<ToolConfig<IntercomListConversationsParams, any>, 'params' | 'request'>
export const intercomListConversationsTool: ToolConfig<
IntercomListConversationsParams,
IntercomListConversationsResponse
> = {
id: 'intercom_list_conversations',
name: 'List Conversations from Intercom',
description: 'List all conversations from Intercom with pagination support',
version: '1.0.0',
...listConversationsBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'list_conversations')
}
const data = await response.json()
return {
success: true,
output: {
conversations: data.conversations || [],
pages: data.pages,
metadata: {
operation: 'list_conversations' as const,
total_count: data.total_count,
},
success: true,
},
}
},
outputs: {
conversations: {
type: 'array',
description: 'Array of conversation objects',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the conversation' },
type: { type: 'string', description: 'Object type (conversation)' },
title: { type: 'string', description: 'Title of the conversation' },
created_at: {
type: 'number',
description: 'Unix timestamp when conversation was created',
},
updated_at: {
type: 'number',
description: 'Unix timestamp when conversation was last updated',
},
waiting_since: { type: 'number', description: 'Unix timestamp when waiting for reply' },
open: { type: 'boolean', description: 'Whether the conversation is open' },
state: { type: 'string', description: 'State of the conversation' },
read: { type: 'boolean', description: 'Whether the conversation has been read' },
priority: { type: 'string', description: 'Priority of the conversation' },
admin_assignee_id: { type: 'number', description: 'ID of assigned admin' },
team_assignee_id: { type: 'string', description: 'ID of assigned team' },
tags: { type: 'object', description: 'Tags on the conversation' },
source: { type: 'object', description: 'Source of the conversation' },
contacts: { type: 'object', description: 'Contacts in the conversation' },
},
},
},
pages: {
type: 'object',
description: 'Pagination information',
properties: {
type: { type: 'string', description: 'Pages type identifier' },
page: { type: 'number', description: 'Current page number' },
per_page: { type: 'number', description: 'Number of results per page' },
total_pages: { type: 'number', description: 'Total number of pages' },
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (list_conversations)' },
total_count: { type: 'number', description: 'Total number of conversations' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
interface IntercomListConversationsV2Response {
success: boolean
output: {
conversations: any[]
pages?: any
total_count?: number
success: boolean
}
}
export const intercomListConversationsV2Tool: ToolConfig<
IntercomListConversationsParams,
IntercomListConversationsV2Response
> = {
...listConversationsBase,
id: 'intercom_list_conversations_v2',
name: 'List Conversations from Intercom',
description: 'List all conversations from Intercom with pagination support',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'list_conversations')
}
const data = await response.json()
return {
success: true,
output: {
conversations: data.conversations ?? null,
pages: data.pages ?? null,
total_count: data.total_count ?? null,
success: true,
},
}
},
outputs: {
conversations: {
type: 'array',
description: 'Array of conversation objects',
optional: true,
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the conversation' },
type: { type: 'string', description: 'Object type (conversation)' },
title: { type: 'string', description: 'Title of the conversation', optional: true },
created_at: {
type: 'number',
description: 'Unix timestamp when conversation was created',
},
updated_at: {
type: 'number',
description: 'Unix timestamp when conversation was last updated',
},
waiting_since: {
type: 'number',
description: 'Unix timestamp when waiting for reply',
optional: true,
},
open: { type: 'boolean', description: 'Whether the conversation is open' },
state: { type: 'string', description: 'State of the conversation' },
read: { type: 'boolean', description: 'Whether the conversation has been read' },
priority: { type: 'string', description: 'Priority of the conversation' },
admin_assignee_id: {
type: 'number',
description: 'ID of assigned admin',
optional: true,
},
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
tags: { type: 'object', description: 'Tags on the conversation' },
source: { type: 'object', description: 'Source of the conversation' },
contacts: { type: 'object', description: 'Contacts in the conversation' },
},
},
},
pages: {
type: 'object',
description: 'Pagination information',
optional: true,
properties: {
type: { type: 'string', description: 'Pages type identifier' },
page: { type: 'number', description: 'Current page number' },
per_page: { type: 'number', description: 'Number of results per page' },
total_pages: { type: 'number', description: 'Total number of pages' },
},
},
total_count: { type: 'number', description: 'Total number of conversations', optional: true },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+86
View File
@@ -0,0 +1,86 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomListTagsParams {
accessToken: string
}
interface IntercomTag {
type: string
id: string
name: string
}
export interface IntercomListTagsV2Response {
success: boolean
output: {
tags: IntercomTag[]
type: string
}
}
const listTagsBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
},
request: {
url: () => buildIntercomUrl('/tags'),
method: 'GET',
headers: (params: IntercomListTagsParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
},
} satisfies Pick<ToolConfig<IntercomListTagsParams, any>, 'params' | 'request'>
export const intercomListTagsV2Tool: ToolConfig<
IntercomListTagsParams,
IntercomListTagsV2Response
> = {
...listTagsBase,
id: 'intercom_list_tags_v2',
name: 'List Tags from Intercom',
description: 'Fetch a list of all tags in the workspace',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'list_tags')
}
const data = await response.json()
return {
success: true,
output: {
tags: data.tags ?? [],
type: data.type ?? 'tag.list',
},
}
},
outputs: {
tags: {
type: 'array',
description: 'Array of tag objects',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the tag' },
type: { type: 'string', description: 'Object type (tag)' },
name: { type: 'string', description: 'Name of the tag' },
},
},
},
type: { type: 'string', description: 'Object type (list)' },
},
}
@@ -0,0 +1,114 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomOpenConversationParams {
accessToken: string
conversationId: string
admin_id: string
}
export interface IntercomOpenConversationV2Response {
success: boolean
output: {
conversation: any
conversationId: string
state: string
}
}
const openConversationBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
conversationId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the conversation to open',
},
admin_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the admin performing the action',
},
},
request: {
url: (params: IntercomOpenConversationParams) =>
buildIntercomUrl(`/conversations/${params.conversationId}/parts`),
method: 'POST',
headers: (params: IntercomOpenConversationParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomOpenConversationParams) => ({
message_type: 'open',
type: 'admin',
admin_id: params.admin_id,
}),
},
} satisfies Pick<ToolConfig<IntercomOpenConversationParams, any>, 'params' | 'request'>
export const intercomOpenConversationV2Tool: ToolConfig<
IntercomOpenConversationParams,
IntercomOpenConversationV2Response
> = {
...openConversationBase,
id: 'intercom_open_conversation_v2',
name: 'Open Conversation in Intercom',
description: 'Open a closed or snoozed conversation in Intercom',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'open_conversation')
}
const data = await response.json()
return {
success: true,
output: {
conversation: {
id: data.id,
type: data.type ?? 'conversation',
state: data.state ?? 'open',
open: data.open ?? true,
read: data.read ?? false,
created_at: data.created_at ?? null,
updated_at: data.updated_at ?? null,
},
conversationId: data.id,
state: data.state ?? 'open',
},
}
},
outputs: {
conversation: {
type: 'object',
description: 'The opened conversation object',
properties: {
id: { type: 'string', description: 'Unique identifier for the conversation' },
type: { type: 'string', description: 'Object type (conversation)' },
state: { type: 'string', description: 'State of the conversation (open)' },
open: { type: 'boolean', description: 'Whether the conversation is open (true)' },
read: { type: 'boolean', description: 'Whether the conversation has been read' },
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when conversation was last updated',
},
},
},
conversationId: { type: 'string', description: 'ID of the opened conversation' },
state: { type: 'string', description: 'State of the conversation (open)' },
},
}
@@ -0,0 +1,249 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomReplyConversationParams {
accessToken: string
conversationId: string
message_type: string
body: string
admin_id?: string
attachment_urls?: string
created_at?: number
}
export interface IntercomReplyConversationResponse {
success: boolean
output: {
conversation: any
metadata: {
operation: 'reply_conversation'
conversationId: string
}
success: boolean
}
}
const replyConversationBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
conversationId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Conversation ID to reply to',
},
message_type: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Message type: "comment" or "note"',
},
body: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The text body of the reply',
},
admin_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'The ID of the admin authoring the reply. If not provided, a default admin (Operator/Fin) will be used.',
},
attachment_urls: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Comma-separated list of image URLs (max 10)',
},
created_at: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description:
'Unix timestamp for when the reply was created. If not provided, current time is used.',
},
},
request: {
url: (params: IntercomReplyConversationParams) =>
buildIntercomUrl(`/conversations/${params.conversationId}/reply`),
method: 'POST',
headers: (params: IntercomReplyConversationParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomReplyConversationParams) => {
const reply: any = {
message_type: params.message_type,
type: 'admin',
body: params.body,
}
if (params.admin_id) reply.admin_id = params.admin_id
if (params.attachment_urls) {
reply.attachment_urls = params.attachment_urls
.split(',')
.map((url) => url.trim())
.slice(0, 10)
}
if (params.created_at) reply.created_at = params.created_at
return reply
},
},
} satisfies Pick<ToolConfig<IntercomReplyConversationParams, any>, 'params' | 'request'>
export const intercomReplyConversationTool: ToolConfig<
IntercomReplyConversationParams,
IntercomReplyConversationResponse
> = {
id: 'intercom_reply_conversation',
name: 'Reply to Conversation in Intercom',
description: 'Reply to a conversation as an admin in Intercom',
version: '1.0.0',
...replyConversationBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'reply_conversation')
}
const data = await response.json()
return {
success: true,
output: {
conversation: data,
metadata: {
operation: 'reply_conversation' as const,
conversationId: data.id,
},
success: true,
},
}
},
outputs: {
conversation: {
type: 'object',
description: 'Updated conversation object',
properties: {
id: { type: 'string', description: 'Unique identifier for the conversation' },
type: { type: 'string', description: 'Object type (conversation)' },
title: { type: 'string', description: 'Title of the conversation', optional: true },
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when conversation was last updated',
},
waiting_since: {
type: 'number',
description: 'Unix timestamp when waiting for reply',
optional: true,
},
open: { type: 'boolean', description: 'Whether the conversation is open' },
state: { type: 'string', description: 'State of the conversation' },
read: { type: 'boolean', description: 'Whether the conversation has been read' },
priority: { type: 'string', description: 'Priority of the conversation' },
admin_assignee_id: { type: 'number', description: 'ID of assigned admin', optional: true },
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
tags: { type: 'object', description: 'Tags on the conversation' },
source: { type: 'object', description: 'Source of the conversation' },
contacts: { type: 'object', description: 'Contacts in the conversation' },
conversation_parts: { type: 'object', description: 'Parts of the conversation' },
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (reply_conversation)' },
conversationId: { type: 'string', description: 'ID of the conversation' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
interface IntercomReplyConversationV2Response {
success: boolean
output: {
conversation: any
conversationId: string
success: boolean
}
}
export const intercomReplyConversationV2Tool: ToolConfig<
IntercomReplyConversationParams,
IntercomReplyConversationV2Response
> = {
...replyConversationBase,
id: 'intercom_reply_conversation_v2',
name: 'Reply to Conversation in Intercom',
description: 'Reply to a conversation as an admin in Intercom',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'reply_conversation')
}
const data = await response.json()
return {
success: true,
output: {
conversation: data,
conversationId: data.id,
success: true,
},
}
},
outputs: {
conversation: {
type: 'object',
description: 'Updated conversation object',
properties: {
id: { type: 'string', description: 'Unique identifier for the conversation' },
type: { type: 'string', description: 'Object type (conversation)' },
title: { type: 'string', description: 'Title of the conversation', optional: true },
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when conversation was last updated',
},
waiting_since: {
type: 'number',
description: 'Unix timestamp when waiting for reply',
optional: true,
},
open: { type: 'boolean', description: 'Whether the conversation is open' },
state: { type: 'string', description: 'State of the conversation' },
read: { type: 'boolean', description: 'Whether the conversation has been read' },
priority: { type: 'string', description: 'Priority of the conversation' },
admin_assignee_id: { type: 'number', description: 'ID of assigned admin', optional: true },
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
tags: { type: 'object', description: 'Tags on the conversation' },
source: { type: 'object', description: 'Source of the conversation' },
contacts: { type: 'object', description: 'Contacts in the conversation' },
conversation_parts: { type: 'object', description: 'Parts of the conversation' },
},
},
conversationId: { type: 'string', description: 'ID of the conversation' },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+425
View File
@@ -0,0 +1,425 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomSearchContactsParams {
accessToken: string
query: string
per_page?: number
starting_after?: string
sort_field?: string
sort_order?: 'ascending' | 'descending'
}
export interface IntercomSearchContactsResponse {
success: boolean
output: {
contacts: Array<{
id: string
type: string
role: string
email: string | null
phone: string | null
name: string | null
avatar: string | null
owner_id: string | null
external_id: string | null
created_at: number
updated_at: number
signed_up_at: number | null
last_seen_at: number | null
workspace_id: string
custom_attributes: Record<string, any>
tags: {
type: string
url: string
data: any[]
has_more: boolean
total_count: number
}
notes: {
type: string
url: string
data: any[]
has_more: boolean
total_count: number
}
companies: {
type: string
url: string
data: any[]
has_more: boolean
total_count: number
}
location: {
type: string
city: string | null
region: string | null
country: string | null
country_code: string | null
continent_code: string | null
}
social_profiles: {
type: string
data: any[]
}
unsubscribed_from_emails: boolean
[key: string]: any
}>
pages: {
type: string
page: number
per_page: number
total_pages: number
}
metadata: {
operation: 'search_contacts'
total_count: number
}
success: boolean
}
}
const searchContactsBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
query: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Search query (e.g., {"field":"email","operator":"=","value":"user@example.com"})',
},
per_page: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page (max: 150)',
},
starting_after: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor for pagination',
},
sort_field: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Field to sort by (e.g., "name", "created_at", "last_seen_at")',
},
sort_order: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Sort order: "ascending" or "descending"',
},
},
request: {
url: () => buildIntercomUrl('/contacts/search'),
method: 'POST',
headers: (params: IntercomSearchContactsParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomSearchContactsParams) => {
let query
try {
query = JSON.parse(params.query)
} catch (error) {
// If not JSON, treat as simple text search
query = {
field: 'name',
operator: '~',
value: params.query,
}
}
const body: any = { query }
if (params.per_page) body.pagination = { per_page: params.per_page }
if (params.starting_after)
body.pagination = { ...body.pagination, starting_after: params.starting_after }
if (params.sort_field) {
body.sort = {
field: params.sort_field,
order: params.sort_order || 'descending',
}
}
return body
},
},
} satisfies Pick<ToolConfig<IntercomSearchContactsParams, any>, 'params' | 'request'>
export const intercomSearchContactsTool: ToolConfig<
IntercomSearchContactsParams,
IntercomSearchContactsResponse
> = {
id: 'intercom_search_contacts',
name: 'Search Contacts in Intercom',
description: 'Search for contacts in Intercom using a query',
version: '1.0.0',
...searchContactsBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'search_contacts')
}
const data = await response.json()
return {
success: true,
output: {
contacts: data.data || [],
pages: data.pages,
metadata: {
operation: 'search_contacts' as const,
total_count: data.total_count,
},
success: true,
},
}
},
outputs: {
contacts: {
type: 'array',
description: 'Array of matching contact objects',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the contact' },
type: { type: 'string', description: 'Object type (contact)' },
role: { type: 'string', description: 'Role of the contact (user or lead)' },
email: { type: 'string', description: 'Email address of the contact' },
phone: { type: 'string', description: 'Phone number of the contact' },
name: { type: 'string', description: 'Name of the contact' },
avatar: { type: 'string', description: 'Avatar URL of the contact' },
owner_id: { type: 'string', description: 'ID of the admin assigned to this contact' },
external_id: { type: 'string', description: 'External identifier for the contact' },
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when contact was last updated',
},
signed_up_at: { type: 'number', description: 'Unix timestamp when user signed up' },
last_seen_at: { type: 'number', description: 'Unix timestamp when user was last seen' },
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
custom_attributes: {
type: 'object',
description: 'Custom attributes set on the contact',
},
tags: { type: 'object', description: 'Tags associated with the contact' },
notes: { type: 'object', description: 'Notes associated with the contact' },
companies: { type: 'object', description: 'Companies associated with the contact' },
location: { type: 'object', description: 'Location information for the contact' },
social_profiles: { type: 'object', description: 'Social profiles of the contact' },
unsubscribed_from_emails: {
type: 'boolean',
description: 'Whether contact is unsubscribed from emails',
},
},
},
},
pages: {
type: 'object',
description: 'Pagination information',
properties: {
type: { type: 'string', description: 'Pages type identifier' },
page: { type: 'number', description: 'Current page number' },
per_page: { type: 'number', description: 'Number of results per page' },
total_pages: { type: 'number', description: 'Total number of pages' },
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (search_contacts)' },
total_count: { type: 'number', description: 'Total number of matching contacts' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
interface IntercomSearchContactsV2Response {
success: boolean
output: {
contacts: Array<{
id: string
type: string
role: string
email: string | null
phone: string | null
name: string | null
avatar: string | null
owner_id: string | null
external_id: string | null
created_at: number
updated_at: number
signed_up_at: number | null
last_seen_at: number | null
workspace_id: string
custom_attributes: Record<string, any>
tags: {
type: string
url: string
data: any[]
has_more: boolean
total_count: number
}
notes: {
type: string
url: string
data: any[]
has_more: boolean
total_count: number
}
companies: {
type: string
url: string
data: any[]
has_more: boolean
total_count: number
}
location: {
type: string
city: string | null
region: string | null
country: string | null
country_code: string | null
continent_code: string | null
}
social_profiles: {
type: string
data: any[]
}
unsubscribed_from_emails: boolean
[key: string]: any
}>
pages: {
type: string
page: number
per_page: number
total_pages: number
}
total_count: number
}
}
export const intercomSearchContactsV2Tool: ToolConfig<
IntercomSearchContactsParams,
IntercomSearchContactsV2Response
> = {
...searchContactsBase,
id: 'intercom_search_contacts_v2',
name: 'Search Contacts in Intercom',
description: 'Search for contacts in Intercom using a query',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'search_contacts')
}
const data = await response.json()
return {
success: true,
output: {
contacts: data.data ?? null,
pages: data.pages ?? null,
total_count: data.total_count ?? null,
},
}
},
outputs: {
contacts: {
type: 'array',
description: 'Array of matching contact objects',
optional: true,
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the contact' },
type: { type: 'string', description: 'Object type (contact)' },
role: { type: 'string', description: 'Role of the contact (user or lead)' },
email: { type: 'string', description: 'Email address of the contact', optional: true },
phone: { type: 'string', description: 'Phone number of the contact', optional: true },
name: { type: 'string', description: 'Name of the contact', optional: true },
avatar: { type: 'string', description: 'Avatar URL of the contact', optional: true },
owner_id: {
type: 'string',
description: 'ID of the admin assigned to this contact',
optional: true,
},
external_id: {
type: 'string',
description: 'External identifier for the contact',
optional: true,
},
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when contact was last updated',
},
signed_up_at: {
type: 'number',
description: 'Unix timestamp when user signed up',
optional: true,
},
last_seen_at: {
type: 'number',
description: 'Unix timestamp when user was last seen',
optional: true,
},
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
custom_attributes: {
type: 'object',
description: 'Custom attributes set on the contact',
},
tags: { type: 'object', description: 'Tags associated with the contact', optional: true },
notes: { type: 'object', description: 'Notes associated with the contact' },
companies: { type: 'object', description: 'Companies associated with the contact' },
location: { type: 'object', description: 'Location information for the contact' },
social_profiles: { type: 'object', description: 'Social profiles of the contact' },
unsubscribed_from_emails: {
type: 'boolean',
description: 'Whether contact is unsubscribed from emails',
},
},
},
},
pages: {
type: 'object',
description: 'Pagination information',
optional: true,
properties: {
type: { type: 'string', description: 'Pages type identifier' },
page: { type: 'number', description: 'Current page number' },
per_page: { type: 'number', description: 'Number of results per page' },
total_pages: { type: 'number', description: 'Total number of pages' },
},
},
total_count: {
type: 'number',
description: 'Total number of matching contacts',
optional: true,
},
},
}
@@ -0,0 +1,295 @@
import { createLogger } from '@sim/logger'
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('IntercomSearchConversations')
export interface IntercomSearchConversationsParams {
accessToken: string
query: string
per_page?: number
starting_after?: string
sort_field?: string
sort_order?: 'ascending' | 'descending'
}
export interface IntercomSearchConversationsResponse {
success: boolean
output: {
conversations: any[]
pages?: any
metadata: {
operation: 'search_conversations'
total_count?: number
}
success: boolean
}
}
export interface IntercomSearchConversationsV2Response {
success: boolean
output: {
conversations: any[]
pages?: any
total_count?: number
success: boolean
}
}
const searchConversationsBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
query: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Search query as JSON object',
},
per_page: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page (max: 150)',
},
starting_after: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor for pagination',
},
sort_field: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Field to sort by (e.g., "created_at", "updated_at")',
},
sort_order: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Sort order: "ascending" or "descending"',
},
},
request: {
url: () => buildIntercomUrl('/conversations/search'),
method: 'POST',
headers: (params: IntercomSearchConversationsParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomSearchConversationsParams) => {
let query
try {
query = JSON.parse(params.query)
} catch (error) {
logger.warn('Failed to parse search query, using default', { error })
query = {
field: 'updated_at',
operator: '>',
value: Math.floor(Date.now() / 1000) - 86400, // Last 24 hours
}
}
const body: any = { query }
if (params.per_page) body.pagination = { per_page: params.per_page }
if (params.starting_after)
body.pagination = { ...body.pagination, starting_after: params.starting_after }
if (params.sort_field) {
body.sort = {
field: params.sort_field,
order: params.sort_order || 'descending',
}
}
return body
},
},
} satisfies Pick<ToolConfig<IntercomSearchConversationsParams, any>, 'params' | 'request'>
export const intercomSearchConversationsTool: ToolConfig<
IntercomSearchConversationsParams,
IntercomSearchConversationsResponse
> = {
id: 'intercom_search_conversations',
name: 'Search Conversations in Intercom',
description: 'Search for conversations in Intercom using a query',
version: '1.0.0',
...searchConversationsBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'search_conversations')
}
const data = await response.json()
return {
success: true,
output: {
conversations: data.conversations || [],
pages: data.pages,
metadata: {
operation: 'search_conversations' as const,
total_count: data.total_count,
},
success: true,
},
}
},
outputs: {
conversations: {
type: 'array',
description: 'Array of matching conversation objects',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the conversation' },
type: { type: 'string', description: 'Object type (conversation)' },
title: { type: 'string', description: 'Title of the conversation' },
created_at: {
type: 'number',
description: 'Unix timestamp when conversation was created',
},
updated_at: {
type: 'number',
description: 'Unix timestamp when conversation was last updated',
},
waiting_since: { type: 'number', description: 'Unix timestamp when waiting for reply' },
open: { type: 'boolean', description: 'Whether the conversation is open' },
state: { type: 'string', description: 'State of the conversation' },
read: { type: 'boolean', description: 'Whether the conversation has been read' },
priority: { type: 'string', description: 'Priority of the conversation' },
admin_assignee_id: { type: 'number', description: 'ID of assigned admin' },
team_assignee_id: { type: 'string', description: 'ID of assigned team' },
tags: { type: 'object', description: 'Tags on the conversation' },
source: { type: 'object', description: 'Source of the conversation' },
contacts: { type: 'object', description: 'Contacts in the conversation' },
},
},
},
pages: {
type: 'object',
description: 'Pagination information',
properties: {
type: { type: 'string', description: 'Pages type identifier' },
page: { type: 'number', description: 'Current page number' },
per_page: { type: 'number', description: 'Number of results per page' },
total_pages: { type: 'number', description: 'Total number of pages' },
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: {
type: 'string',
description: 'The operation performed (search_conversations)',
},
total_count: { type: 'number', description: 'Total number of matching conversations' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
export const intercomSearchConversationsV2Tool: ToolConfig<
IntercomSearchConversationsParams,
IntercomSearchConversationsV2Response
> = {
...searchConversationsBase,
id: 'intercom_search_conversations_v2',
name: 'Search Conversations in Intercom',
description:
'Search for conversations in Intercom using a query. Returns API-aligned fields only.',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'search_conversations')
}
const data = await response.json()
return {
success: true,
output: {
conversations: data.conversations ?? null,
pages: data.pages ?? null,
total_count: data.total_count ?? null,
success: true,
},
}
},
outputs: {
conversations: {
type: 'array',
description: 'Array of matching conversation objects',
optional: true,
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the conversation' },
type: { type: 'string', description: 'Object type (conversation)' },
title: { type: 'string', description: 'Title of the conversation', optional: true },
created_at: {
type: 'number',
description: 'Unix timestamp when conversation was created',
},
updated_at: {
type: 'number',
description: 'Unix timestamp when conversation was last updated',
},
waiting_since: {
type: 'number',
description: 'Unix timestamp when waiting for reply',
optional: true,
},
open: { type: 'boolean', description: 'Whether the conversation is open' },
state: { type: 'string', description: 'State of the conversation' },
read: { type: 'boolean', description: 'Whether the conversation has been read' },
priority: { type: 'string', description: 'Priority of the conversation' },
admin_assignee_id: {
type: 'number',
description: 'ID of assigned admin',
optional: true,
},
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
tags: { type: 'object', description: 'Tags on the conversation' },
source: { type: 'object', description: 'Source of the conversation' },
contacts: { type: 'object', description: 'Contacts in the conversation' },
},
},
},
pages: {
type: 'object',
description: 'Pagination information',
optional: true,
properties: {
type: { type: 'string', description: 'Pages type identifier' },
page: { type: 'number', description: 'Current page number' },
per_page: { type: 'number', description: 'Number of results per page' },
total_pages: { type: 'number', description: 'Total number of pages' },
},
},
total_count: {
type: 'number',
description: 'Total number of matching conversations',
optional: true,
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
@@ -0,0 +1,124 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomSnoozeConversationParams {
accessToken: string
conversationId: string
admin_id: string
snoozed_until: number
}
export interface IntercomSnoozeConversationV2Response {
success: boolean
output: {
conversation: any
conversationId: string
state: string
snoozed_until: number | null
}
}
const snoozeConversationBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
conversationId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the conversation to snooze',
},
admin_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the admin performing the action',
},
snoozed_until: {
type: 'number',
required: true,
visibility: 'user-or-llm',
description: 'Unix timestamp for when the conversation should reopen',
},
},
request: {
url: (params: IntercomSnoozeConversationParams) =>
buildIntercomUrl(`/conversations/${params.conversationId}/reply`),
method: 'POST',
headers: (params: IntercomSnoozeConversationParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomSnoozeConversationParams) => ({
message_type: 'snoozed',
admin_id: params.admin_id,
snoozed_until: params.snoozed_until,
}),
},
} satisfies Pick<ToolConfig<IntercomSnoozeConversationParams, any>, 'params' | 'request'>
export const intercomSnoozeConversationV2Tool: ToolConfig<
IntercomSnoozeConversationParams,
IntercomSnoozeConversationV2Response
> = {
...snoozeConversationBase,
id: 'intercom_snooze_conversation_v2',
name: 'Snooze Conversation in Intercom',
description: 'Snooze a conversation to reopen at a future time',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'snooze_conversation')
}
const data = await response.json()
return {
success: true,
output: {
conversation: data,
conversationId: data.id,
state: data.state ?? 'snoozed',
snoozed_until: data.snoozed_until ?? null,
},
}
},
outputs: {
conversation: {
type: 'object',
description: 'The snoozed conversation object',
properties: {
id: { type: 'string', description: 'Unique identifier for the conversation' },
type: { type: 'string', description: 'Object type (conversation)' },
state: { type: 'string', description: 'State of the conversation (snoozed)' },
open: { type: 'boolean', description: 'Whether the conversation is open' },
snoozed_until: {
type: 'number',
description: 'Unix timestamp when conversation will reopen',
optional: true,
},
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
updated_at: {
type: 'number',
description: 'Unix timestamp when conversation was last updated',
},
},
},
conversationId: { type: 'string', description: 'ID of the snoozed conversation' },
state: { type: 'string', description: 'State of the conversation (snoozed)' },
snoozed_until: {
type: 'number',
description: 'Unix timestamp when conversation will reopen',
optional: true,
},
},
}
+89
View File
@@ -0,0 +1,89 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomTagContactParams {
accessToken: string
contactId: string
tagId: string
}
export interface IntercomTagContactV2Response {
success: boolean
output: {
id: string
name: string
type: string
}
}
const tagContactBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
contactId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the contact to tag',
},
tagId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the tag to apply',
},
},
request: {
url: (params: IntercomTagContactParams) =>
buildIntercomUrl(`/contacts/${params.contactId}/tags`),
method: 'POST',
headers: (params: IntercomTagContactParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomTagContactParams) => ({
id: params.tagId,
}),
},
} satisfies Pick<ToolConfig<IntercomTagContactParams, any>, 'params' | 'request'>
export const intercomTagContactV2Tool: ToolConfig<
IntercomTagContactParams,
IntercomTagContactV2Response
> = {
...tagContactBase,
id: 'intercom_tag_contact_v2',
name: 'Tag Contact in Intercom',
description: 'Add a tag to a specific contact',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'tag_contact')
}
const data = await response.json()
return {
success: true,
output: {
id: data.id,
name: data.name,
type: data.type ?? 'tag',
},
}
},
outputs: {
id: { type: 'string', description: 'Unique identifier for the tag' },
name: { type: 'string', description: 'Name of the tag' },
type: { type: 'string', description: 'Object type (tag)' },
},
}
@@ -0,0 +1,97 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomTagConversationParams {
accessToken: string
conversationId: string
tagId: string
admin_id: string
}
export interface IntercomTagConversationV2Response {
success: boolean
output: {
id: string
name: string
type: string
}
}
const tagConversationBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
conversationId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the conversation to tag',
},
tagId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the tag to apply',
},
admin_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the admin applying the tag',
},
},
request: {
url: (params: IntercomTagConversationParams) =>
buildIntercomUrl(`/conversations/${params.conversationId}/tags`),
method: 'POST',
headers: (params: IntercomTagConversationParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomTagConversationParams) => ({
id: params.tagId,
admin_id: params.admin_id,
}),
},
} satisfies Pick<ToolConfig<IntercomTagConversationParams, any>, 'params' | 'request'>
export const intercomTagConversationV2Tool: ToolConfig<
IntercomTagConversationParams,
IntercomTagConversationV2Response
> = {
...tagConversationBase,
id: 'intercom_tag_conversation_v2',
name: 'Tag Conversation in Intercom',
description: 'Add a tag to a specific conversation',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'tag_conversation')
}
const data = await response.json()
return {
success: true,
output: {
id: data.id,
name: data.name,
type: data.type ?? 'tag',
},
}
},
outputs: {
id: { type: 'string', description: 'Unique identifier for the tag' },
name: { type: 'string', description: 'Name of the tag' },
type: { type: 'string', description: 'Object type (tag)' },
},
}
File diff suppressed because it is too large Load Diff
+87
View File
@@ -0,0 +1,87 @@
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
export interface IntercomUntagContactParams {
accessToken: string
contactId: string
tagId: string
}
export interface IntercomUntagContactV2Response {
success: boolean
output: {
id: string
name: string
type: string
}
}
const untagContactBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
contactId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the contact to untag',
},
tagId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the tag to remove',
},
},
request: {
url: (params: IntercomUntagContactParams) =>
buildIntercomUrl(`/contacts/${params.contactId}/tags/${params.tagId}`),
method: 'DELETE',
headers: (params: IntercomUntagContactParams) => ({
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
},
} satisfies Pick<ToolConfig<IntercomUntagContactParams, any>, 'params' | 'request'>
export const intercomUntagContactV2Tool: ToolConfig<
IntercomUntagContactParams,
IntercomUntagContactV2Response
> = {
...untagContactBase,
id: 'intercom_untag_contact_v2',
name: 'Untag Contact in Intercom',
description: 'Remove a tag from a specific contact',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'untag_contact')
}
const data = await response.json()
return {
success: true,
output: {
id: data.id,
name: data.name,
type: data.type ?? 'tag',
},
}
},
outputs: {
id: { type: 'string', description: 'Unique identifier for the tag that was removed' },
name: { type: 'string', description: 'Name of the tag that was removed' },
type: { type: 'string', description: 'Object type (tag)' },
},
}
+317
View File
@@ -0,0 +1,317 @@
import { createLogger } from '@sim/logger'
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('IntercomUpdateContact')
export interface IntercomUpdateContactParams {
accessToken: string
contactId: string
role?: 'user' | 'lead'
external_id?: string
email?: string
phone?: string
name?: string
avatar?: string
signed_up_at?: number
last_seen_at?: number
owner_id?: string
unsubscribed_from_emails?: boolean
custom_attributes?: string
company_id?: string
}
export interface IntercomUpdateContactResponse {
success: boolean
output: {
contact: any
metadata: {
operation: 'update_contact'
contactId: string
}
success: boolean
}
}
const intercomUpdateContactBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
contactId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Contact ID to update',
},
role: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: "The role of the contact. Accepts 'user' or 'lead'.",
},
external_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'A unique identifier for the contact provided by the client',
},
email: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: "The contact's email address",
},
phone: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: "The contact's phone number",
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: "The contact's name",
},
avatar: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'An avatar image URL for the contact',
},
signed_up_at: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'The time the user signed up as a Unix timestamp',
},
last_seen_at: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'The time the user was last seen as a Unix timestamp',
},
owner_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The id of an admin that has been assigned account ownership of the contact',
},
unsubscribed_from_emails: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether the contact is unsubscribed from emails',
},
custom_attributes: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Custom attributes as JSON object (e.g., {"attribute_name": "value"})',
},
company_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company ID to associate the contact with',
},
},
request: {
url: (params) => buildIntercomUrl(`/contacts/${params.contactId}`),
method: 'PUT',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params) => {
const contact: any = {}
if (params.role) contact.role = params.role
if (params.external_id) contact.external_id = params.external_id
if (params.email) contact.email = params.email
if (params.phone) contact.phone = params.phone
if (params.name) contact.name = params.name
if (params.avatar) contact.avatar = params.avatar
if (params.signed_up_at) contact.signed_up_at = params.signed_up_at
if (params.last_seen_at) contact.last_seen_at = params.last_seen_at
if (params.owner_id) contact.owner_id = params.owner_id
if (params.unsubscribed_from_emails !== undefined)
contact.unsubscribed_from_emails = params.unsubscribed_from_emails
if (params.custom_attributes) {
try {
contact.custom_attributes = JSON.parse(params.custom_attributes)
} catch (error) {
logger.warn('Failed to parse custom attributes', { error })
}
}
if (params.company_id) contact.company_id = params.company_id
return contact
},
},
} satisfies Pick<ToolConfig<IntercomUpdateContactParams, any>, 'params' | 'request'>
export const intercomUpdateContactTool: ToolConfig<
IntercomUpdateContactParams,
IntercomUpdateContactResponse
> = {
id: 'intercom_update_contact',
name: 'Update Contact in Intercom',
description: 'Update an existing contact in Intercom',
version: '1.0.0',
...intercomUpdateContactBase,
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'update_contact')
}
const data = await response.json()
return {
success: true,
output: {
contact: data,
metadata: {
operation: 'update_contact' as const,
contactId: data.id,
},
success: true,
},
}
},
outputs: {
contact: {
type: 'object',
description: 'Updated contact object',
properties: {
id: { type: 'string', description: 'Unique identifier for the contact' },
type: { type: 'string', description: 'Object type (contact)' },
role: { type: 'string', description: 'Role of the contact (user or lead)' },
email: { type: 'string', description: 'Email address of the contact', optional: true },
phone: { type: 'string', description: 'Phone number of the contact', optional: true },
name: { type: 'string', description: 'Name of the contact', optional: true },
avatar: { type: 'string', description: 'Avatar URL of the contact', optional: true },
owner_id: {
type: 'string',
description: 'ID of the admin assigned to this contact',
optional: true,
},
external_id: {
type: 'string',
description: 'External identifier for the contact',
optional: true,
},
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
updated_at: { type: 'number', description: 'Unix timestamp when contact was last updated' },
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
custom_attributes: { type: 'object', description: 'Custom attributes set on the contact' },
tags: { type: 'object', description: 'Tags associated with the contact' },
notes: { type: 'object', description: 'Notes associated with the contact' },
companies: { type: 'object', description: 'Companies associated with the contact' },
location: { type: 'object', description: 'Location information for the contact' },
social_profiles: { type: 'object', description: 'Social profiles of the contact' },
unsubscribed_from_emails: {
type: 'boolean',
description: 'Whether contact is unsubscribed from emails',
},
},
},
metadata: {
type: 'object',
description: 'Operation metadata',
properties: {
operation: { type: 'string', description: 'The operation performed (update_contact)' },
contactId: { type: 'string', description: 'ID of the updated contact' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
interface IntercomUpdateContactV2Response {
success: boolean
output: {
contact: any
contactId: string
}
}
export const intercomUpdateContactV2Tool: ToolConfig<
IntercomUpdateContactParams,
IntercomUpdateContactV2Response
> = {
...intercomUpdateContactBase,
id: 'intercom_update_contact_v2',
name: 'Update Contact in Intercom',
description: 'Update an existing contact in Intercom. Returns API-aligned fields only.',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'update_contact')
}
const data = await response.json()
return {
success: true,
output: {
contact: data,
contactId: data.id,
},
}
},
outputs: {
contact: {
type: 'object',
description: 'Updated contact object',
properties: {
id: { type: 'string', description: 'Unique identifier for the contact' },
type: { type: 'string', description: 'Object type (contact)' },
role: { type: 'string', description: 'Role of the contact (user or lead)' },
email: { type: 'string', description: 'Email address of the contact', optional: true },
phone: { type: 'string', description: 'Phone number of the contact', optional: true },
name: { type: 'string', description: 'Name of the contact', optional: true },
avatar: { type: 'string', description: 'Avatar URL of the contact', optional: true },
owner_id: {
type: 'string',
description: 'ID of the admin assigned to this contact',
optional: true,
},
external_id: {
type: 'string',
description: 'External identifier for the contact',
optional: true,
},
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
updated_at: { type: 'number', description: 'Unix timestamp when contact was last updated' },
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
custom_attributes: { type: 'object', description: 'Custom attributes set on the contact' },
tags: { type: 'object', description: 'Tags associated with the contact' },
notes: { type: 'object', description: 'Notes associated with the contact' },
companies: { type: 'object', description: 'Companies associated with the contact' },
location: { type: 'object', description: 'Location information for the contact' },
social_profiles: { type: 'object', description: 'Social profiles of the contact' },
unsubscribed_from_emails: {
type: 'boolean',
description: 'Whether contact is unsubscribed from emails',
},
},
},
contactId: { type: 'string', description: 'ID of the updated contact' },
},
}
+193
View File
@@ -0,0 +1,193 @@
import { createLogger } from '@sim/logger'
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('IntercomUpdateTicket')
export interface IntercomUpdateTicketParams {
accessToken: string
ticketId: string
ticket_attributes?: string
open?: boolean
is_shared?: boolean
snoozed_until?: number
admin_id?: string
assignee_id?: string
}
export interface IntercomUpdateTicketV2Response {
success: boolean
output: {
ticket: any
ticketId: string
ticket_state: string
}
}
const updateTicketBase = {
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Intercom API access token',
},
ticketId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the ticket to update',
},
ticket_attributes: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'JSON object with ticket attributes (e.g., {"_default_title_":"New Title","_default_description_":"Updated description"})',
},
open: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Set to false to close the ticket, true to keep it open',
},
is_shared: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether the ticket is visible to users',
},
snoozed_until: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Unix timestamp for when the ticket should reopen',
},
admin_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'The ID of the admin performing the update (needed for workflows and attribution)',
},
assignee_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The ID of the admin or team to assign the ticket to. Set to "0" to unassign.',
},
},
request: {
url: (params: IntercomUpdateTicketParams) => buildIntercomUrl(`/tickets/${params.ticketId}`),
method: 'PUT',
headers: (params: IntercomUpdateTicketParams) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
'Intercom-Version': '2.14',
}),
body: (params: IntercomUpdateTicketParams) => {
const payload: any = {}
if (params.ticket_attributes) {
try {
payload.ticket_attributes = JSON.parse(params.ticket_attributes)
} catch (error) {
logger.error('Failed to parse ticket_attributes', { error })
throw new Error('ticket_attributes must be a valid JSON object')
}
}
if (params.open !== undefined) {
payload.open = params.open
}
if (params.is_shared !== undefined) {
payload.is_shared = params.is_shared
}
if (params.snoozed_until !== undefined) {
payload.snoozed_until = params.snoozed_until
}
if (params.admin_id) {
payload.admin_id = params.admin_id
}
if (params.assignee_id) {
payload.assignee_id = params.assignee_id
}
return payload
},
},
} satisfies Pick<ToolConfig<IntercomUpdateTicketParams, any>, 'params' | 'request'>
export const intercomUpdateTicketV2Tool: ToolConfig<
IntercomUpdateTicketParams,
IntercomUpdateTicketV2Response
> = {
...updateTicketBase,
id: 'intercom_update_ticket_v2',
name: 'Update Ticket in Intercom',
description: 'Update a ticket in Intercom (change state, assignment, attributes)',
version: '2.0.0',
transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
handleIntercomError(data, response.status, 'update_ticket')
}
const data = await response.json()
return {
success: true,
output: {
ticket: {
id: data.id,
type: data.type ?? 'ticket',
ticket_id: data.ticket_id ?? null,
ticket_state: data.ticket_state ?? null,
ticket_attributes: data.ticket_attributes ?? null,
open: data.open ?? null,
is_shared: data.is_shared ?? null,
snoozed_until: data.snoozed_until ?? null,
admin_assignee_id: data.admin_assignee_id ?? null,
team_assignee_id: data.team_assignee_id ?? null,
created_at: data.created_at ?? null,
updated_at: data.updated_at ?? null,
},
ticketId: data.id,
ticket_state: data.ticket_state ?? null,
},
}
},
outputs: {
ticket: {
type: 'object',
description: 'The updated ticket object',
properties: {
id: { type: 'string', description: 'Unique identifier for the ticket' },
type: { type: 'string', description: 'Object type (ticket)' },
ticket_id: { type: 'string', description: 'Ticket ID shown in Intercom UI' },
ticket_state: { type: 'string', description: 'State of the ticket' },
ticket_attributes: { type: 'object', description: 'Attributes of the ticket' },
open: { type: 'boolean', description: 'Whether the ticket is open' },
is_shared: { type: 'boolean', description: 'Whether the ticket is visible to users' },
snoozed_until: {
type: 'number',
description: 'Unix timestamp when ticket will reopen',
optional: true,
},
admin_assignee_id: { type: 'string', description: 'ID of assigned admin', optional: true },
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
created_at: { type: 'number', description: 'Unix timestamp when ticket was created' },
updated_at: { type: 'number', description: 'Unix timestamp when ticket was last updated' },
},
},
ticketId: { type: 'string', description: 'ID of the updated ticket' },
ticket_state: { type: 'string', description: 'Current state of the ticket' },
},
}