From 87025030edf60f917b86d90fdd765681f677ee49 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Thu, 26 Feb 2026 11:26:04 -0800 Subject: [PATCH 1/6] feat(devin): add devin integration for autonomous coding sessions --- apps/docs/components/icons.tsx | 24 +++ apps/docs/components/ui/icon-mapping.ts | 14 +- apps/docs/content/docs/en/tools/devin.mdx | 117 ++++++++++++++ apps/docs/content/docs/en/tools/meta.json | 3 +- apps/sim/blocks/blocks/devin.ts | 187 ++++++++++++++++++++++ apps/sim/blocks/registry.ts | 2 + apps/sim/components/icons.tsx | 24 +++ apps/sim/tools/devin/create-session.ts | 105 ++++++++++++ apps/sim/tools/devin/get-session.ts | 70 ++++++++ apps/sim/tools/devin/index.ts | 4 + apps/sim/tools/devin/list-sessions.ts | 72 +++++++++ apps/sim/tools/devin/send-message.ts | 84 ++++++++++ apps/sim/tools/devin/types.ts | 168 +++++++++++++++++++ apps/sim/tools/registry.ts | 10 ++ 14 files changed, 877 insertions(+), 7 deletions(-) create mode 100644 apps/docs/content/docs/en/tools/devin.mdx create mode 100644 apps/sim/blocks/blocks/devin.ts create mode 100644 apps/sim/tools/devin/create-session.ts create mode 100644 apps/sim/tools/devin/get-session.ts create mode 100644 apps/sim/tools/devin/index.ts create mode 100644 apps/sim/tools/devin/list-sessions.ts create mode 100644 apps/sim/tools/devin/send-message.ts create mode 100644 apps/sim/tools/devin/types.ts diff --git a/apps/docs/components/icons.tsx b/apps/docs/components/icons.tsx index 8d8d161ecb0..2d64e29e24d 100644 --- a/apps/docs/components/icons.tsx +++ b/apps/docs/components/icons.tsx @@ -939,6 +939,30 @@ export function GoogleIcon(props: SVGProps) { ) } +export function DevinIcon(props: SVGProps) { + return ( + + + + + + ) +} + export function DiscordIcon(props: SVGProps) { return ( > @@ -174,6 +175,7 @@ export const blockTypeToIconMap: Record = { confluence_v2: ConfluenceIcon, cursor_v2: CursorIcon, datadog: DatadogIcon, + devin: DevinIcon, discord: DiscordIcon, dropbox: DropboxIcon, dspy: DsPyIcon, diff --git a/apps/docs/content/docs/en/tools/devin.mdx b/apps/docs/content/docs/en/tools/devin.mdx new file mode 100644 index 00000000000..023641ac1a0 --- /dev/null +++ b/apps/docs/content/docs/en/tools/devin.mdx @@ -0,0 +1,117 @@ +--- +title: Devin +description: Autonomous AI software engineer +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +## Usage Instructions + +Integrate Devin into your workflow. Create sessions to assign coding tasks, send messages to guide active sessions, and retrieve session status and results. Devin autonomously writes, runs, and tests code. + + + +## Tools + +### `devin_create_session` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `sessionId` | string | Session identifier | +| `url` | string | URL to view the session in Devin UI | +| `status` | string | Session status \(new, claimed, running, exit, error, suspended, resuming\) | +| `statusDetail` | string | Detailed status \(working, waiting_for_user, finished, etc.\) | +| `title` | string | Session title | +| `createdAt` | number | Creation timestamp \(Unix\) | +| `updatedAt` | number | Last updated timestamp \(Unix\) | +| `acusConsumed` | number | ACUs consumed | +| `tags` | json | Session tags | +| `pullRequests` | json | Pull requests created during the session | +| `structuredOutput` | json | Structured output from the session | +| `sessions` | json | List of sessions | + +### `devin_get_session` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `sessionId` | string | Session identifier | +| `url` | string | URL to view the session in Devin UI | +| `status` | string | Session status \(new, claimed, running, exit, error, suspended, resuming\) | +| `statusDetail` | string | Detailed status \(working, waiting_for_user, finished, etc.\) | +| `title` | string | Session title | +| `createdAt` | number | Creation timestamp \(Unix\) | +| `updatedAt` | number | Last updated timestamp \(Unix\) | +| `acusConsumed` | number | ACUs consumed | +| `tags` | json | Session tags | +| `pullRequests` | json | Pull requests created during the session | +| `structuredOutput` | json | Structured output from the session | +| `sessions` | json | List of sessions | + +### `devin_list_sessions` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `sessionId` | string | Session identifier | +| `url` | string | URL to view the session in Devin UI | +| `status` | string | Session status \(new, claimed, running, exit, error, suspended, resuming\) | +| `statusDetail` | string | Detailed status \(working, waiting_for_user, finished, etc.\) | +| `title` | string | Session title | +| `createdAt` | number | Creation timestamp \(Unix\) | +| `updatedAt` | number | Last updated timestamp \(Unix\) | +| `acusConsumed` | number | ACUs consumed | +| `tags` | json | Session tags | +| `pullRequests` | json | Pull requests created during the session | +| `structuredOutput` | json | Structured output from the session | +| `sessions` | json | List of sessions | + +### `devin_send_message` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `sessionId` | string | Session identifier | +| `url` | string | URL to view the session in Devin UI | +| `status` | string | Session status \(new, claimed, running, exit, error, suspended, resuming\) | +| `statusDetail` | string | Detailed status \(working, waiting_for_user, finished, etc.\) | +| `title` | string | Session title | +| `createdAt` | number | Creation timestamp \(Unix\) | +| `updatedAt` | number | Last updated timestamp \(Unix\) | +| `acusConsumed` | number | ACUs consumed | +| `tags` | json | Session tags | +| `pullRequests` | json | Pull requests created during the session | +| `structuredOutput` | json | Structured output from the session | +| `sessions` | json | List of sessions | + + diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index cc1a22ca005..64a5f12964d 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -21,6 +21,7 @@ "confluence", "cursor", "datadog", + "devin", "discord", "dropbox", "dspy", @@ -149,4 +150,4 @@ "zep", "zoom" ] -} +} \ No newline at end of file diff --git a/apps/sim/blocks/blocks/devin.ts b/apps/sim/blocks/blocks/devin.ts new file mode 100644 index 00000000000..8289fc3476c --- /dev/null +++ b/apps/sim/blocks/blocks/devin.ts @@ -0,0 +1,187 @@ +import { DevinIcon } from '@/components/icons' +import type { BlockConfig } from '@/blocks/types' +import { AuthMode } from '@/blocks/types' + +export const DevinBlock: BlockConfig = { + type: 'devin', + name: 'Devin', + description: 'Autonomous AI software engineer', + longDescription: + 'Integrate Devin into your workflow. Create sessions to assign coding tasks, send messages to guide active sessions, and retrieve session status and results. Devin autonomously writes, runs, and tests code.', + bestPractices: ` + - Write clear, specific prompts describing the task, expected outcome, and any constraints. + - Use playbook IDs to standardize recurring task patterns across sessions. + - Set ACU limits to control cost for long-running tasks. + - Use Get Session to poll for completion status before consuming structured output. + - Send Message auto-resumes suspended sessions — no need to resume separately. + `, + docsLink: 'https://docs.sim.ai/tools/devin', + category: 'tools', + bgColor: '#12141A', + icon: DevinIcon, + authMode: AuthMode.ApiKey, + subBlocks: [ + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + options: [ + { label: 'Create Session', id: 'create_session' }, + { label: 'Get Session', id: 'get_session' }, + { label: 'List Sessions', id: 'list_sessions' }, + { label: 'Send Message', id: 'send_message' }, + ], + value: () => 'create_session', + }, + { + id: 'apiKey', + title: 'API Key', + type: 'short-input', + placeholder: 'Enter your Devin API key (cog_...)', + password: true, + required: true, + }, + { + id: 'prompt', + title: 'Prompt', + type: 'long-input', + placeholder: 'Describe the task for Devin...', + required: { field: 'operation', value: 'create_session' }, + condition: { field: 'operation', value: 'create_session' }, + wandConfig: { + enabled: true, + prompt: `You are an expert at writing clear, actionable prompts for Devin, an autonomous AI software engineer. Generate or refine a task prompt based on the user's request. + +Current prompt: {context} + +RULES: +1. Be specific about the expected outcome and deliverables +2. Include relevant technical context (languages, frameworks, repos) +3. Specify any constraints (don't modify certain files, follow certain patterns) +4. Break complex tasks into clear steps when helpful +5. Return ONLY the prompt text, no markdown formatting or explanations`, + placeholder: 'Describe what you want Devin to do...', + }, + }, + { + id: 'playbookId', + title: 'Playbook ID', + type: 'short-input', + placeholder: 'Optional playbook ID to guide the session', + condition: { field: 'operation', value: 'create_session' }, + mode: 'advanced', + }, + { + id: 'maxAcuLimit', + title: 'Max ACU Limit', + type: 'short-input', + placeholder: 'Maximum ACU budget for this session', + condition: { field: 'operation', value: 'create_session' }, + mode: 'advanced', + }, + { + id: 'tags', + title: 'Tags', + type: 'short-input', + placeholder: 'Comma-separated tags', + condition: { field: 'operation', value: 'create_session' }, + mode: 'advanced', + }, + { + id: 'sessionId', + title: 'Session ID', + type: 'short-input', + placeholder: 'Enter session ID', + required: { field: 'operation', value: ['get_session', 'send_message'] }, + condition: { field: 'operation', value: ['get_session', 'send_message'] }, + }, + { + id: 'message', + title: 'Message', + type: 'long-input', + placeholder: 'Enter message to send to Devin...', + required: { field: 'operation', value: 'send_message' }, + condition: { field: 'operation', value: 'send_message' }, + }, + { + id: 'limit', + title: 'Limit', + type: 'short-input', + placeholder: 'Number of sessions (1-200, default: 100)', + condition: { field: 'operation', value: 'list_sessions' }, + mode: 'advanced', + }, + ], + tools: { + access: [ + 'devin_create_session', + 'devin_get_session', + 'devin_list_sessions', + 'devin_send_message', + ], + config: { + tool: (params) => `devin_${params.operation}`, + params: (params) => { + if (params.maxAcuLimit != null && params.maxAcuLimit !== '') { + params.maxAcuLimit = Number(params.maxAcuLimit) + } + if (params.limit != null && params.limit !== '') { + params.limit = Number(params.limit) + } + return params + }, + }, + }, + inputs: { + prompt: { type: 'string', description: 'Task prompt for Devin' }, + sessionId: { type: 'string', description: 'Session ID' }, + message: { type: 'string', description: 'Message to send to the session' }, + apiKey: { type: 'string', description: 'Devin API key' }, + playbookId: { type: 'string', description: 'Playbook ID to guide the session' }, + maxAcuLimit: { type: 'number', description: 'Maximum ACU limit' }, + tags: { type: 'string', description: 'Comma-separated tags' }, + limit: { type: 'number', description: 'Number of sessions to return' }, + }, + outputs: { + sessionId: { type: 'string', description: 'Session identifier' }, + url: { type: 'string', description: 'URL to view the session in Devin UI' }, + status: { + type: 'string', + description: 'Session status (new, claimed, running, exit, error, suspended, resuming)', + }, + statusDetail: { + type: 'string', + description: 'Detailed status (working, waiting_for_user, finished, etc.)', + condition: { field: 'operation', value: 'list_sessions', not: true }, + }, + title: { type: 'string', description: 'Session title' }, + createdAt: { type: 'number', description: 'Creation timestamp (Unix)' }, + updatedAt: { type: 'number', description: 'Last updated timestamp (Unix)' }, + acusConsumed: { + type: 'number', + description: 'ACUs consumed', + condition: { field: 'operation', value: 'list_sessions', not: true }, + }, + tags: { type: 'json', description: 'Session tags' }, + pullRequests: { + type: 'json', + description: 'Pull requests created during the session', + condition: { field: 'operation', value: 'list_sessions', not: true }, + }, + structuredOutput: { + type: 'json', + description: 'Structured output from the session', + condition: { field: 'operation', value: 'list_sessions', not: true }, + }, + playbookId: { + type: 'string', + description: 'Associated playbook ID', + condition: { field: 'operation', value: 'list_sessions', not: true }, + }, + sessions: { + type: 'json', + description: 'List of sessions', + condition: { field: 'operation', value: 'list_sessions' }, + }, + }, +} diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index 8d3ef317f6d..eff25ffb1d7 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -23,6 +23,7 @@ import { ConditionBlock } from '@/blocks/blocks/condition' import { ConfluenceBlock, ConfluenceV2Block } from '@/blocks/blocks/confluence' import { CursorBlock, CursorV2Block } from '@/blocks/blocks/cursor' import { DatadogBlock } from '@/blocks/blocks/datadog' +import { DevinBlock } from '@/blocks/blocks/devin' import { DiscordBlock } from '@/blocks/blocks/discord' import { DropboxBlock } from '@/blocks/blocks/dropbox' import { DSPyBlock } from '@/blocks/blocks/dspy' @@ -206,6 +207,7 @@ export const registry: Record = { cursor: CursorBlock, cursor_v2: CursorV2Block, datadog: DatadogBlock, + devin: DevinBlock, discord: DiscordBlock, dropbox: DropboxBlock, dspy: DSPyBlock, diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx index 8d8d161ecb0..2d64e29e24d 100644 --- a/apps/sim/components/icons.tsx +++ b/apps/sim/components/icons.tsx @@ -939,6 +939,30 @@ export function GoogleIcon(props: SVGProps) { ) } +export function DevinIcon(props: SVGProps) { + return ( + + + + + + ) +} + export function DiscordIcon(props: SVGProps) { return ( = { + id: 'devin_create_session', + name: 'Devin Create Session', + description: + 'Create a new Devin session with a prompt. Devin will autonomously work on the task described in the prompt.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + prompt: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The task prompt for Devin to work on', + }, + playbookId: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Optional playbook ID to guide the session', + }, + maxAcuLimit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum ACU limit for the session', + }, + tags: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Comma-separated tags for the session', + }, + }, + + request: { + url: 'https://api.devin.ai/v3/organizations/sessions', + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + const body: Record = { + prompt: params.prompt, + } + if (params.playbookId) body.playbook_id = params.playbookId + if (params.maxAcuLimit != null && params.maxAcuLimit !== '') { + body.max_acu_limit = Number(params.maxAcuLimit) + } + if (params.tags) { + body.tags = params.tags.split(',').map((t: string) => t.trim()) + } + return body + }, + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + return { + success: true, + output: { + sessionId: data.session_id ?? null, + url: data.url ?? null, + status: data.status ?? null, + statusDetail: data.status_detail ?? null, + title: data.title ?? null, + createdAt: data.created_at ?? null, + updatedAt: data.updated_at ?? null, + acusConsumed: data.acus_consumed ?? null, + tags: data.tags ?? null, + pullRequests: data.pull_requests ?? null, + structuredOutput: data.structured_output ?? null, + playbookId: data.playbook_id ?? null, + }, + } + }, + + outputs: { + sessionId: DEVIN_SESSION_OUTPUT_PROPERTIES.sessionId, + url: DEVIN_SESSION_OUTPUT_PROPERTIES.url, + status: DEVIN_SESSION_OUTPUT_PROPERTIES.status, + statusDetail: DEVIN_SESSION_OUTPUT_PROPERTIES.statusDetail, + title: DEVIN_SESSION_OUTPUT_PROPERTIES.title, + createdAt: DEVIN_SESSION_OUTPUT_PROPERTIES.createdAt, + updatedAt: DEVIN_SESSION_OUTPUT_PROPERTIES.updatedAt, + acusConsumed: DEVIN_SESSION_OUTPUT_PROPERTIES.acusConsumed, + tags: DEVIN_SESSION_OUTPUT_PROPERTIES.tags, + pullRequests: DEVIN_SESSION_OUTPUT_PROPERTIES.pullRequests, + structuredOutput: DEVIN_SESSION_OUTPUT_PROPERTIES.structuredOutput, + playbookId: DEVIN_SESSION_OUTPUT_PROPERTIES.playbookId, + }, +} diff --git a/apps/sim/tools/devin/get-session.ts b/apps/sim/tools/devin/get-session.ts new file mode 100644 index 00000000000..74edefbb6ee --- /dev/null +++ b/apps/sim/tools/devin/get-session.ts @@ -0,0 +1,70 @@ +import type { ToolConfig } from '@/tools/types' +import type { DevinGetSessionParams, DevinGetSessionResponse } from './types' +import { DEVIN_SESSION_OUTPUT_PROPERTIES } from './types' + +export const devinGetSessionTool: ToolConfig = { + id: 'devin_get_session', + name: 'Devin Get Session', + description: + 'Retrieve details of an existing Devin session including status, tags, pull requests, and structured output.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + sessionId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The session ID to retrieve', + }, + }, + + request: { + url: (params) => `https://api.devin.ai/v3/organizations/sessions/${params.sessionId}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + return { + success: true, + output: { + sessionId: data.session_id ?? null, + url: data.url ?? null, + status: data.status ?? null, + statusDetail: data.status_detail ?? null, + title: data.title ?? null, + createdAt: data.created_at ?? null, + updatedAt: data.updated_at ?? null, + acusConsumed: data.acus_consumed ?? null, + tags: data.tags ?? null, + pullRequests: data.pull_requests ?? null, + structuredOutput: data.structured_output ?? null, + playbookId: data.playbook_id ?? null, + }, + } + }, + + outputs: { + sessionId: DEVIN_SESSION_OUTPUT_PROPERTIES.sessionId, + url: DEVIN_SESSION_OUTPUT_PROPERTIES.url, + status: DEVIN_SESSION_OUTPUT_PROPERTIES.status, + statusDetail: DEVIN_SESSION_OUTPUT_PROPERTIES.statusDetail, + title: DEVIN_SESSION_OUTPUT_PROPERTIES.title, + createdAt: DEVIN_SESSION_OUTPUT_PROPERTIES.createdAt, + updatedAt: DEVIN_SESSION_OUTPUT_PROPERTIES.updatedAt, + acusConsumed: DEVIN_SESSION_OUTPUT_PROPERTIES.acusConsumed, + tags: DEVIN_SESSION_OUTPUT_PROPERTIES.tags, + pullRequests: DEVIN_SESSION_OUTPUT_PROPERTIES.pullRequests, + structuredOutput: DEVIN_SESSION_OUTPUT_PROPERTIES.structuredOutput, + playbookId: DEVIN_SESSION_OUTPUT_PROPERTIES.playbookId, + }, +} diff --git a/apps/sim/tools/devin/index.ts b/apps/sim/tools/devin/index.ts new file mode 100644 index 00000000000..91a2e42801b --- /dev/null +++ b/apps/sim/tools/devin/index.ts @@ -0,0 +1,4 @@ +export { devinCreateSessionTool } from './create-session' +export { devinGetSessionTool } from './get-session' +export { devinListSessionsTool } from './list-sessions' +export { devinSendMessageTool } from './send-message' diff --git a/apps/sim/tools/devin/list-sessions.ts b/apps/sim/tools/devin/list-sessions.ts new file mode 100644 index 00000000000..4cf1853a81b --- /dev/null +++ b/apps/sim/tools/devin/list-sessions.ts @@ -0,0 +1,72 @@ +import type { ToolConfig } from '@/tools/types' +import type { DevinListSessionsParams, DevinListSessionsResponse } from './types' +import { DEVIN_SESSION_LIST_ITEM_PROPERTIES } from './types' + +export const devinListSessionsTool: ToolConfig< + DevinListSessionsParams, + DevinListSessionsResponse +> = { + id: 'devin_list_sessions', + name: 'Devin List Sessions', + description: 'List Devin sessions in the organization. Returns up to 100 sessions by default.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of sessions to return (1-200, default: 100)', + }, + }, + + request: { + url: (params) => { + const searchParams = new URLSearchParams() + if (params.limit) searchParams.set('first', String(Number(params.limit))) + const qs = searchParams.toString() + return `https://api.devin.ai/v3/organizations/sessions${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + const items = data.items ?? [] + return { + success: true, + output: { + sessions: items.map((item: Record) => ({ + sessionId: item.session_id ?? null, + url: item.url ?? null, + status: item.status ?? null, + statusDetail: item.status_detail ?? null, + title: item.title ?? null, + createdAt: item.created_at ?? null, + updatedAt: item.updated_at ?? null, + tags: item.tags ?? null, + })), + }, + } + }, + + outputs: { + sessions: { + type: 'array', + description: 'List of Devin sessions', + items: { + type: 'object', + properties: DEVIN_SESSION_LIST_ITEM_PROPERTIES, + }, + }, + }, +} diff --git a/apps/sim/tools/devin/send-message.ts b/apps/sim/tools/devin/send-message.ts new file mode 100644 index 00000000000..ab85b4aea17 --- /dev/null +++ b/apps/sim/tools/devin/send-message.ts @@ -0,0 +1,84 @@ +import type { ToolConfig } from '@/tools/types' +import type { DevinSendMessageParams, DevinSendMessageResponse } from './types' +import { DEVIN_SESSION_OUTPUT_PROPERTIES } from './types' + +export const devinSendMessageTool: ToolConfig< + DevinSendMessageParams, + DevinSendMessageResponse +> = { + id: 'devin_send_message', + name: 'Devin Send Message', + description: + 'Send a message to a Devin session. If the session is suspended, it will be automatically resumed. Returns the updated session state.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + sessionId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The session ID to send the message to', + }, + message: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The message to send to Devin', + }, + }, + + request: { + url: (params) => + `https://api.devin.ai/v3/organizations/sessions/${params.sessionId}/messages`, + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => ({ + message: params.message, + }), + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + return { + success: true, + output: { + sessionId: data.session_id ?? null, + url: data.url ?? null, + status: data.status ?? null, + statusDetail: data.status_detail ?? null, + title: data.title ?? null, + createdAt: data.created_at ?? null, + updatedAt: data.updated_at ?? null, + acusConsumed: data.acus_consumed ?? null, + tags: data.tags ?? null, + pullRequests: data.pull_requests ?? null, + structuredOutput: data.structured_output ?? null, + playbookId: data.playbook_id ?? null, + }, + } + }, + + outputs: { + sessionId: DEVIN_SESSION_OUTPUT_PROPERTIES.sessionId, + url: DEVIN_SESSION_OUTPUT_PROPERTIES.url, + status: DEVIN_SESSION_OUTPUT_PROPERTIES.status, + statusDetail: DEVIN_SESSION_OUTPUT_PROPERTIES.statusDetail, + title: DEVIN_SESSION_OUTPUT_PROPERTIES.title, + createdAt: DEVIN_SESSION_OUTPUT_PROPERTIES.createdAt, + updatedAt: DEVIN_SESSION_OUTPUT_PROPERTIES.updatedAt, + acusConsumed: DEVIN_SESSION_OUTPUT_PROPERTIES.acusConsumed, + tags: DEVIN_SESSION_OUTPUT_PROPERTIES.tags, + pullRequests: DEVIN_SESSION_OUTPUT_PROPERTIES.pullRequests, + structuredOutput: DEVIN_SESSION_OUTPUT_PROPERTIES.structuredOutput, + playbookId: DEVIN_SESSION_OUTPUT_PROPERTIES.playbookId, + }, +} diff --git a/apps/sim/tools/devin/types.ts b/apps/sim/tools/devin/types.ts new file mode 100644 index 00000000000..f38653819bb --- /dev/null +++ b/apps/sim/tools/devin/types.ts @@ -0,0 +1,168 @@ +import type { OutputProperty, ToolResponse } from '@/tools/types' + +export interface DevinCreateSessionParams { + apiKey: string + prompt: string + playbookId?: string + maxAcuLimit?: number + tags?: string +} + +export interface DevinGetSessionParams { + apiKey: string + sessionId: string +} + +export interface DevinListSessionsParams { + apiKey: string + limit?: number +} + +export interface DevinSendMessageParams { + apiKey: string + sessionId: string + message: string +} + +export const DEVIN_SESSION_OUTPUT_PROPERTIES = { + sessionId: { + type: 'string', + description: 'Unique identifier for the session', + }, + url: { + type: 'string', + description: 'URL to view the session in the Devin UI', + }, + status: { + type: 'string', + description: 'Session status (new, claimed, running, exit, error, suspended, resuming)', + }, + statusDetail: { + type: 'string', + description: + 'Detailed status (working, waiting_for_user, waiting_for_approval, finished, inactivity, etc.)', + optional: true, + }, + title: { + type: 'string', + description: 'Session title', + optional: true, + }, + createdAt: { + type: 'number', + description: 'Unix timestamp when the session was created', + optional: true, + }, + updatedAt: { + type: 'number', + description: 'Unix timestamp when the session was last updated', + optional: true, + }, + acusConsumed: { + type: 'number', + description: 'ACUs consumed by the session', + optional: true, + }, + tags: { + type: 'json', + description: 'Tags associated with the session', + optional: true, + }, + pullRequests: { + type: 'json', + description: 'Pull requests created during the session', + optional: true, + }, + structuredOutput: { + type: 'json', + description: 'Structured output from the session', + optional: true, + }, + playbookId: { + type: 'string', + description: 'Associated playbook ID', + optional: true, + }, +} as const satisfies Record + +export const DEVIN_SESSION_LIST_ITEM_PROPERTIES = { + sessionId: { + type: 'string', + description: 'Unique identifier for the session', + }, + url: { + type: 'string', + description: 'URL to view the session', + }, + status: { + type: 'string', + description: 'Session status', + }, + statusDetail: { + type: 'string', + description: 'Detailed status', + optional: true, + }, + title: { + type: 'string', + description: 'Session title', + optional: true, + }, + createdAt: { + type: 'number', + description: 'Creation timestamp (Unix)', + optional: true, + }, + updatedAt: { + type: 'number', + description: 'Last updated timestamp (Unix)', + optional: true, + }, + tags: { + type: 'json', + description: 'Session tags', + optional: true, + }, +} as const satisfies Record + +export interface DevinSessionOutput { + sessionId: string + url: string + status: string + statusDetail: string | null + title: string | null + createdAt: number | null + updatedAt: number | null + acusConsumed: number | null + tags: string[] | null + pullRequests: Array<{ pr_url: string; pr_state: string | null }> | null + structuredOutput: Record | null + playbookId: string | null +} + +export interface DevinCreateSessionResponse extends ToolResponse { + output: DevinSessionOutput +} + +export interface DevinGetSessionResponse extends ToolResponse { + output: DevinSessionOutput +} + +export interface DevinListSessionsResponse extends ToolResponse { + output: { + sessions: Array<{ + sessionId: string + url: string + status: string + statusDetail: string | null + title: string | null + createdAt: number | null + updatedAt: number | null + tags: string[] | null + }> + } +} + +export interface DevinSendMessageResponse extends ToolResponse { + output: DevinSessionOutput +} diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index c6ddacafde9..287c264f605 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -311,6 +311,12 @@ import { dropboxSearchTool, dropboxUploadTool, } from '@/tools/dropbox' +import { + devinCreateSessionTool, + devinGetSessionTool, + devinListSessionsTool, + devinSendMessageTool, +} from '@/tools/devin' import { chainOfThoughtTool, predictTool, reactTool } from '@/tools/dspy' import { duckduckgoSearchTool } from '@/tools/duckduckgo' import { @@ -2585,6 +2591,10 @@ export const tools: Record = { dropbox_get_metadata: dropboxGetMetadataTool, dropbox_create_shared_link: dropboxCreateSharedLinkTool, dropbox_search: dropboxSearchTool, + devin_create_session: devinCreateSessionTool, + devin_get_session: devinGetSessionTool, + devin_list_sessions: devinListSessionsTool, + devin_send_message: devinSendMessageTool, duckduckgo_search: duckduckgoSearchTool, dspy_predict: predictTool, dspy_chain_of_thought: chainOfThoughtTool, From 3b80072e7d46eedd7a89ed52e9eaa67aa9bf48db Mon Sep 17 00:00:00 2001 From: waleed Date: Thu, 26 Feb 2026 11:27:31 -0800 Subject: [PATCH 2/6] lint --- apps/docs/components/icons.tsx | 19 ++-- apps/docs/components/ui/icon-mapping.ts | 12 +-- apps/docs/content/docs/en/tools/meta.json | 2 +- apps/sim/components/icons.tsx | 19 ++-- apps/sim/tools/devin/list-sessions.ts | 118 +++++++++++----------- apps/sim/tools/devin/send-message.ts | 8 +- apps/sim/tools/registry.ts | 12 +-- 7 files changed, 87 insertions(+), 103 deletions(-) diff --git a/apps/docs/components/icons.tsx b/apps/docs/components/icons.tsx index 2d64e29e24d..9e68974089e 100644 --- a/apps/docs/components/icons.tsx +++ b/apps/docs/components/icons.tsx @@ -941,23 +941,18 @@ export function GoogleIcon(props: SVGProps) { export function DevinIcon(props: SVGProps) { return ( - + ) diff --git a/apps/docs/components/ui/icon-mapping.ts b/apps/docs/components/ui/icon-mapping.ts index 5d222bd9063..822ce48aeb1 100644 --- a/apps/docs/components/ui/icon-mapping.ts +++ b/apps/docs/components/ui/icon-mapping.ts @@ -39,8 +39,8 @@ import { EyeIcon, FirecrawlIcon, FirefliesIcon, - GitLabIcon, GithubIcon, + GitLabIcon, GmailIcon, GongIcon, GoogleBigQueryIcon, @@ -76,9 +76,9 @@ import { LinearIcon, LinkedInIcon, LinkupIcon, - MailServerIcon, MailchimpIcon, MailgunIcon, + MailServerIcon, Mem0Icon, MicrosoftDataverseIcon, MicrosoftExcelIcon, @@ -111,8 +111,6 @@ import { ResendIcon, RevenueCatIcon, S3Icon, - SQSIcon, - STTIcon, SalesforceIcon, SearchIcon, SendgridIcon, @@ -124,17 +122,19 @@ import { SimilarwebIcon, SlackIcon, SmtpIcon, + SQSIcon, SshIcon, + STTIcon, StagehandIcon, StripeIcon, SupabaseIcon, - TTSIcon, TavilyIcon, TelegramIcon, TextractIcon, TinybirdIcon, TranslateIcon, TrelloIcon, + TTSIcon, TwilioIcon, TypeformIcon, UpstashIcon, @@ -145,11 +145,11 @@ import { WhatsAppIcon, WikipediaIcon, WordpressIcon, + xIcon, YouTubeIcon, ZendeskIcon, ZepIcon, ZoomIcon, - xIcon, } from '@/components/icons' type IconComponent = ComponentType> diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index 64a5f12964d..a089247e2e7 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -150,4 +150,4 @@ "zep", "zoom" ] -} \ No newline at end of file +} diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx index 2d64e29e24d..9e68974089e 100644 --- a/apps/sim/components/icons.tsx +++ b/apps/sim/components/icons.tsx @@ -941,23 +941,18 @@ export function GoogleIcon(props: SVGProps) { export function DevinIcon(props: SVGProps) { return ( - + ) diff --git a/apps/sim/tools/devin/list-sessions.ts b/apps/sim/tools/devin/list-sessions.ts index 4cf1853a81b..d9f05812b71 100644 --- a/apps/sim/tools/devin/list-sessions.ts +++ b/apps/sim/tools/devin/list-sessions.ts @@ -2,71 +2,69 @@ import type { ToolConfig } from '@/tools/types' import type { DevinListSessionsParams, DevinListSessionsResponse } from './types' import { DEVIN_SESSION_LIST_ITEM_PROPERTIES } from './types' -export const devinListSessionsTool: ToolConfig< - DevinListSessionsParams, - DevinListSessionsResponse -> = { - id: 'devin_list_sessions', - name: 'Devin List Sessions', - description: 'List Devin sessions in the organization. Returns up to 100 sessions by default.', - version: '1.0.0', +export const devinListSessionsTool: ToolConfig = + { + id: 'devin_list_sessions', + name: 'Devin List Sessions', + description: 'List Devin sessions in the organization. Returns up to 100 sessions by default.', + version: '1.0.0', - params: { - apiKey: { - type: 'string', - required: true, - visibility: 'user-only', - description: 'Devin API key (service user credential starting with cog_)', - }, - limit: { - type: 'number', - required: false, - visibility: 'user-or-llm', - description: 'Maximum number of sessions to return (1-200, default: 100)', + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of sessions to return (1-200, default: 100)', + }, }, - }, - request: { - url: (params) => { - const searchParams = new URLSearchParams() - if (params.limit) searchParams.set('first', String(Number(params.limit))) - const qs = searchParams.toString() - return `https://api.devin.ai/v3/organizations/sessions${qs ? `?${qs}` : ''}` + request: { + url: (params) => { + const searchParams = new URLSearchParams() + if (params.limit) searchParams.set('first', String(Number(params.limit))) + const qs = searchParams.toString() + return `https://api.devin.ai/v3/organizations/sessions${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), }, - method: 'GET', - headers: (params) => ({ - Authorization: `Bearer ${params.apiKey}`, - }), - }, - transformResponse: async (response: Response) => { - const data = await response.json() - const items = data.items ?? [] - return { - success: true, - output: { - sessions: items.map((item: Record) => ({ - sessionId: item.session_id ?? null, - url: item.url ?? null, - status: item.status ?? null, - statusDetail: item.status_detail ?? null, - title: item.title ?? null, - createdAt: item.created_at ?? null, - updatedAt: item.updated_at ?? null, - tags: item.tags ?? null, - })), - }, - } - }, + transformResponse: async (response: Response) => { + const data = await response.json() + const items = data.items ?? [] + return { + success: true, + output: { + sessions: items.map((item: Record) => ({ + sessionId: item.session_id ?? null, + url: item.url ?? null, + status: item.status ?? null, + statusDetail: item.status_detail ?? null, + title: item.title ?? null, + createdAt: item.created_at ?? null, + updatedAt: item.updated_at ?? null, + tags: item.tags ?? null, + })), + }, + } + }, - outputs: { - sessions: { - type: 'array', - description: 'List of Devin sessions', - items: { - type: 'object', - properties: DEVIN_SESSION_LIST_ITEM_PROPERTIES, + outputs: { + sessions: { + type: 'array', + description: 'List of Devin sessions', + items: { + type: 'object', + properties: DEVIN_SESSION_LIST_ITEM_PROPERTIES, + }, }, }, - }, -} + } diff --git a/apps/sim/tools/devin/send-message.ts b/apps/sim/tools/devin/send-message.ts index ab85b4aea17..76a95acb788 100644 --- a/apps/sim/tools/devin/send-message.ts +++ b/apps/sim/tools/devin/send-message.ts @@ -2,10 +2,7 @@ import type { ToolConfig } from '@/tools/types' import type { DevinSendMessageParams, DevinSendMessageResponse } from './types' import { DEVIN_SESSION_OUTPUT_PROPERTIES } from './types' -export const devinSendMessageTool: ToolConfig< - DevinSendMessageParams, - DevinSendMessageResponse -> = { +export const devinSendMessageTool: ToolConfig = { id: 'devin_send_message', name: 'Devin Send Message', description: @@ -34,8 +31,7 @@ export const devinSendMessageTool: ToolConfig< }, request: { - url: (params) => - `https://api.devin.ai/v3/organizations/sessions/${params.sessionId}/messages`, + url: (params) => `https://api.devin.ai/v3/organizations/sessions/${params.sessionId}/messages`, method: 'POST', headers: (params) => ({ Authorization: `Bearer ${params.apiKey}`, diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index 287c264f605..d8302770c3d 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -262,6 +262,12 @@ import { datadogSendLogsTool, datadogSubmitMetricsTool, } from '@/tools/datadog' +import { + devinCreateSessionTool, + devinGetSessionTool, + devinListSessionsTool, + devinSendMessageTool, +} from '@/tools/devin' import { discordAddReactionTool, discordArchiveThreadTool, @@ -311,12 +317,6 @@ import { dropboxSearchTool, dropboxUploadTool, } from '@/tools/dropbox' -import { - devinCreateSessionTool, - devinGetSessionTool, - devinListSessionsTool, - devinSendMessageTool, -} from '@/tools/devin' import { chainOfThoughtTool, predictTool, reactTool } from '@/tools/dspy' import { duckduckgoSearchTool } from '@/tools/duckduckgo' import { From f789d79d8c7e325257ce8ebb468f77e2dee876de Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Thu, 26 Feb 2026 11:35:10 -0800 Subject: [PATCH 3/6] improvement(devin): update tool names and add manual docs description --- apps/docs/content/docs/en/tools/devin.mdx | 26 +++++ apps/sim/tools/devin/create-session.ts | 2 +- apps/sim/tools/devin/get-session.ts | 2 +- apps/sim/tools/devin/list-sessions.ts | 118 +++++++++++----------- apps/sim/tools/devin/send-message.ts | 2 +- 5 files changed, 89 insertions(+), 61 deletions(-) diff --git a/apps/docs/content/docs/en/tools/devin.mdx b/apps/docs/content/docs/en/tools/devin.mdx index 023641ac1a0..04d95a5905d 100644 --- a/apps/docs/content/docs/en/tools/devin.mdx +++ b/apps/docs/content/docs/en/tools/devin.mdx @@ -10,6 +10,28 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" color="#12141A" /> +{/* MANUAL-CONTENT-START:intro */} +[Devin](https://devin.ai/) is an autonomous AI software engineer by Cognition that can independently write, run, debug, and deploy code. + +With Devin, you can: + +- **Automate coding tasks**: Assign software engineering tasks and let Devin autonomously write, test, and iterate on code +- **Manage sessions**: Create, monitor, and interact with Devin sessions to track progress on assigned tasks +- **Guide active work**: Send messages to running sessions to provide additional context, redirect efforts, or answer questions +- **Retrieve structured output**: Poll completed sessions for pull requests, structured results, and detailed status +- **Control costs**: Set ACU (Autonomous Compute Unit) limits to cap spending on long-running tasks +- **Standardize workflows**: Use playbook IDs to apply repeatable task patterns across sessions + +In Sim, the Devin integration enables your agents to programmatically manage Devin sessions as part of their workflows: + +- **Create sessions**: Kick off new Devin sessions with a prompt describing the task, optional playbook, ACU limits, and tags +- **Get session details**: Retrieve the full state of a session including status, pull requests, structured output, and resource consumption +- **List sessions**: Query all sessions in your organization with optional pagination +- **Send messages**: Communicate with active or suspended sessions to provide guidance, and automatically resume suspended sessions + +This allows for powerful automation scenarios such as triggering code generation from upstream events, polling for completion before consuming results, orchestrating multi-step development pipelines, and integrating Devin's output into broader agent workflows. +{/* MANUAL-CONTENT-END */} + ## Usage Instructions Integrate Devin into your workflow. Create sessions to assign coding tasks, send messages to guide active sessions, and retrieve session status and results. Devin autonomously writes, runs, and tests code. @@ -40,6 +62,7 @@ Integrate Devin into your workflow. Create sessions to assign coding tasks, send | `tags` | json | Session tags | | `pullRequests` | json | Pull requests created during the session | | `structuredOutput` | json | Structured output from the session | +| `playbookId` | string | Associated playbook ID | | `sessions` | json | List of sessions | ### `devin_get_session` @@ -64,6 +87,7 @@ Integrate Devin into your workflow. Create sessions to assign coding tasks, send | `tags` | json | Session tags | | `pullRequests` | json | Pull requests created during the session | | `structuredOutput` | json | Structured output from the session | +| `playbookId` | string | Associated playbook ID | | `sessions` | json | List of sessions | ### `devin_list_sessions` @@ -88,6 +112,7 @@ Integrate Devin into your workflow. Create sessions to assign coding tasks, send | `tags` | json | Session tags | | `pullRequests` | json | Pull requests created during the session | | `structuredOutput` | json | Structured output from the session | +| `playbookId` | string | Associated playbook ID | | `sessions` | json | List of sessions | ### `devin_send_message` @@ -112,6 +137,7 @@ Integrate Devin into your workflow. Create sessions to assign coding tasks, send | `tags` | json | Session tags | | `pullRequests` | json | Pull requests created during the session | | `structuredOutput` | json | Structured output from the session | +| `playbookId` | string | Associated playbook ID | | `sessions` | json | List of sessions | diff --git a/apps/sim/tools/devin/create-session.ts b/apps/sim/tools/devin/create-session.ts index 9c2d93f5653..70be1c8b81b 100644 --- a/apps/sim/tools/devin/create-session.ts +++ b/apps/sim/tools/devin/create-session.ts @@ -7,7 +7,7 @@ export const devinCreateSessionTool: ToolConfig< DevinCreateSessionResponse > = { id: 'devin_create_session', - name: 'Devin Create Session', + name: 'create_session', description: 'Create a new Devin session with a prompt. Devin will autonomously work on the task described in the prompt.', version: '1.0.0', diff --git a/apps/sim/tools/devin/get-session.ts b/apps/sim/tools/devin/get-session.ts index 74edefbb6ee..0af5b309bfb 100644 --- a/apps/sim/tools/devin/get-session.ts +++ b/apps/sim/tools/devin/get-session.ts @@ -4,7 +4,7 @@ import { DEVIN_SESSION_OUTPUT_PROPERTIES } from './types' export const devinGetSessionTool: ToolConfig = { id: 'devin_get_session', - name: 'Devin Get Session', + name: 'get_session', description: 'Retrieve details of an existing Devin session including status, tags, pull requests, and structured output.', version: '1.0.0', diff --git a/apps/sim/tools/devin/list-sessions.ts b/apps/sim/tools/devin/list-sessions.ts index d9f05812b71..53129d1199e 100644 --- a/apps/sim/tools/devin/list-sessions.ts +++ b/apps/sim/tools/devin/list-sessions.ts @@ -2,69 +2,71 @@ import type { ToolConfig } from '@/tools/types' import type { DevinListSessionsParams, DevinListSessionsResponse } from './types' import { DEVIN_SESSION_LIST_ITEM_PROPERTIES } from './types' -export const devinListSessionsTool: ToolConfig = - { - id: 'devin_list_sessions', - name: 'Devin List Sessions', - description: 'List Devin sessions in the organization. Returns up to 100 sessions by default.', - version: '1.0.0', +export const devinListSessionsTool: ToolConfig< + DevinListSessionsParams, + DevinListSessionsResponse +> = { + id: 'devin_list_sessions', + name: 'list_sessions', + description: 'List Devin sessions in the organization. Returns up to 100 sessions by default.', + version: '1.0.0', - params: { - apiKey: { - type: 'string', - required: true, - visibility: 'user-only', - description: 'Devin API key (service user credential starting with cog_)', - }, - limit: { - type: 'number', - required: false, - visibility: 'user-or-llm', - description: 'Maximum number of sessions to return (1-200, default: 100)', - }, + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', }, - - request: { - url: (params) => { - const searchParams = new URLSearchParams() - if (params.limit) searchParams.set('first', String(Number(params.limit))) - const qs = searchParams.toString() - return `https://api.devin.ai/v3/organizations/sessions${qs ? `?${qs}` : ''}` - }, - method: 'GET', - headers: (params) => ({ - Authorization: `Bearer ${params.apiKey}`, - }), + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of sessions to return (1-200, default: 100)', }, + }, - transformResponse: async (response: Response) => { - const data = await response.json() - const items = data.items ?? [] - return { - success: true, - output: { - sessions: items.map((item: Record) => ({ - sessionId: item.session_id ?? null, - url: item.url ?? null, - status: item.status ?? null, - statusDetail: item.status_detail ?? null, - title: item.title ?? null, - createdAt: item.created_at ?? null, - updatedAt: item.updated_at ?? null, - tags: item.tags ?? null, - })), - }, - } + request: { + url: (params) => { + const searchParams = new URLSearchParams() + if (params.limit) searchParams.set('first', String(Number(params.limit))) + const qs = searchParams.toString() + return `https://api.devin.ai/v3/organizations/sessions${qs ? `?${qs}` : ''}` }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + const items = data.items ?? [] + return { + success: true, + output: { + sessions: items.map((item: Record) => ({ + sessionId: item.session_id ?? null, + url: item.url ?? null, + status: item.status ?? null, + statusDetail: item.status_detail ?? null, + title: item.title ?? null, + createdAt: item.created_at ?? null, + updatedAt: item.updated_at ?? null, + tags: item.tags ?? null, + })), + }, + } + }, - outputs: { - sessions: { - type: 'array', - description: 'List of Devin sessions', - items: { - type: 'object', - properties: DEVIN_SESSION_LIST_ITEM_PROPERTIES, - }, + outputs: { + sessions: { + type: 'array', + description: 'List of Devin sessions', + items: { + type: 'object', + properties: DEVIN_SESSION_LIST_ITEM_PROPERTIES, }, }, - } + }, +} diff --git a/apps/sim/tools/devin/send-message.ts b/apps/sim/tools/devin/send-message.ts index 76a95acb788..13844c47032 100644 --- a/apps/sim/tools/devin/send-message.ts +++ b/apps/sim/tools/devin/send-message.ts @@ -4,7 +4,7 @@ import { DEVIN_SESSION_OUTPUT_PROPERTIES } from './types' export const devinSendMessageTool: ToolConfig = { id: 'devin_send_message', - name: 'Devin Send Message', + name: 'send_message', description: 'Send a message to a Devin session. If the session is suspended, it will be automatically resumed. Returns the updated session state.', version: '1.0.0', From c5f652ec7b32cae80e21f5745ab0e4e0716216d6 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Thu, 26 Feb 2026 11:36:23 -0800 Subject: [PATCH 4/6] improvement(devin): rename tool files to snake_case and regenerate docs --- apps/docs/content/docs/en/tools/devin.mdx | 88 +++++++++++-------- .../{create-session.ts => create_session.ts} | 0 .../devin/{get-session.ts => get_session.ts} | 0 apps/sim/tools/devin/index.ts | 8 +- .../{list-sessions.ts => list_sessions.ts} | 0 .../{send-message.ts => send_message.ts} | 0 6 files changed, 55 insertions(+), 41 deletions(-) rename apps/sim/tools/devin/{create-session.ts => create_session.ts} (100%) rename apps/sim/tools/devin/{get-session.ts => get_session.ts} (100%) rename apps/sim/tools/devin/{list-sessions.ts => list_sessions.ts} (100%) rename apps/sim/tools/devin/{send-message.ts => send_message.ts} (100%) diff --git a/apps/docs/content/docs/en/tools/devin.mdx b/apps/docs/content/docs/en/tools/devin.mdx index 04d95a5905d..4ea369fcccb 100644 --- a/apps/docs/content/docs/en/tools/devin.mdx +++ b/apps/docs/content/docs/en/tools/devin.mdx @@ -32,6 +32,7 @@ In Sim, the Devin integration enables your agents to programmatically manage Dev This allows for powerful automation scenarios such as triggering code generation from upstream events, polling for completion before consuming results, orchestrating multi-step development pipelines, and integrating Devin's output into broader agent workflows. {/* MANUAL-CONTENT-END */} + ## Usage Instructions Integrate Devin into your workflow. Create sessions to assign coding tasks, send messages to guide active sessions, and retrieve session status and results. Devin autonomously writes, runs, and tests code. @@ -42,102 +43,115 @@ Integrate Devin into your workflow. Create sessions to assign coding tasks, send ### `devin_create_session` +Create a new Devin session with a prompt. Devin will autonomously work on the task described in the prompt. + #### Input | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `prompt` | string | Yes | The task prompt for Devin to work on | +| `playbookId` | string | No | Optional playbook ID to guide the session | +| `maxAcuLimit` | number | No | Maximum ACU limit for the session | +| `tags` | string | No | Comma-separated tags for the session | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `sessionId` | string | Session identifier | -| `url` | string | URL to view the session in Devin UI | +| `sessionId` | string | Unique identifier for the session | +| `url` | string | URL to view the session in the Devin UI | | `status` | string | Session status \(new, claimed, running, exit, error, suspended, resuming\) | -| `statusDetail` | string | Detailed status \(working, waiting_for_user, finished, etc.\) | +| `statusDetail` | string | Detailed status \(working, waiting_for_user, waiting_for_approval, finished, inactivity, etc.\) | | `title` | string | Session title | -| `createdAt` | number | Creation timestamp \(Unix\) | -| `updatedAt` | number | Last updated timestamp \(Unix\) | -| `acusConsumed` | number | ACUs consumed | -| `tags` | json | Session tags | +| `createdAt` | number | Unix timestamp when the session was created | +| `updatedAt` | number | Unix timestamp when the session was last updated | +| `acusConsumed` | number | ACUs consumed by the session | +| `tags` | json | Tags associated with the session | | `pullRequests` | json | Pull requests created during the session | | `structuredOutput` | json | Structured output from the session | | `playbookId` | string | Associated playbook ID | -| `sessions` | json | List of sessions | ### `devin_get_session` +Retrieve details of an existing Devin session including status, tags, pull requests, and structured output. + #### Input | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `sessionId` | string | Yes | The session ID to retrieve | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `sessionId` | string | Session identifier | -| `url` | string | URL to view the session in Devin UI | +| `sessionId` | string | Unique identifier for the session | +| `url` | string | URL to view the session in the Devin UI | | `status` | string | Session status \(new, claimed, running, exit, error, suspended, resuming\) | -| `statusDetail` | string | Detailed status \(working, waiting_for_user, finished, etc.\) | +| `statusDetail` | string | Detailed status \(working, waiting_for_user, waiting_for_approval, finished, inactivity, etc.\) | | `title` | string | Session title | -| `createdAt` | number | Creation timestamp \(Unix\) | -| `updatedAt` | number | Last updated timestamp \(Unix\) | -| `acusConsumed` | number | ACUs consumed | -| `tags` | json | Session tags | +| `createdAt` | number | Unix timestamp when the session was created | +| `updatedAt` | number | Unix timestamp when the session was last updated | +| `acusConsumed` | number | ACUs consumed by the session | +| `tags` | json | Tags associated with the session | | `pullRequests` | json | Pull requests created during the session | | `structuredOutput` | json | Structured output from the session | | `playbookId` | string | Associated playbook ID | -| `sessions` | json | List of sessions | ### `devin_list_sessions` +List Devin sessions in the organization. Returns up to 100 sessions by default. + #### Input | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `limit` | number | No | Maximum number of sessions to return \(1-200, default: 100\) | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `sessionId` | string | Session identifier | -| `url` | string | URL to view the session in Devin UI | -| `status` | string | Session status \(new, claimed, running, exit, error, suspended, resuming\) | -| `statusDetail` | string | Detailed status \(working, waiting_for_user, finished, etc.\) | -| `title` | string | Session title | -| `createdAt` | number | Creation timestamp \(Unix\) | -| `updatedAt` | number | Last updated timestamp \(Unix\) | -| `acusConsumed` | number | ACUs consumed | -| `tags` | json | Session tags | -| `pullRequests` | json | Pull requests created during the session | -| `structuredOutput` | json | Structured output from the session | -| `playbookId` | string | Associated playbook ID | -| `sessions` | json | List of sessions | +| `sessions` | array | List of Devin sessions | +| ↳ `sessionId` | string | Unique identifier for the session | +| ↳ `url` | string | URL to view the session | +| ↳ `status` | string | Session status | +| ↳ `statusDetail` | string | Detailed status | +| ↳ `title` | string | Session title | +| ↳ `createdAt` | number | Creation timestamp \(Unix\) | +| ↳ `updatedAt` | number | Last updated timestamp \(Unix\) | +| ↳ `tags` | json | Session tags | ### `devin_send_message` +Send a message to a Devin session. If the session is suspended, it will be automatically resumed. Returns the updated session state. + #### Input | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `sessionId` | string | Yes | The session ID to send the message to | +| `message` | string | Yes | The message to send to Devin | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `sessionId` | string | Session identifier | -| `url` | string | URL to view the session in Devin UI | +| `sessionId` | string | Unique identifier for the session | +| `url` | string | URL to view the session in the Devin UI | | `status` | string | Session status \(new, claimed, running, exit, error, suspended, resuming\) | -| `statusDetail` | string | Detailed status \(working, waiting_for_user, finished, etc.\) | +| `statusDetail` | string | Detailed status \(working, waiting_for_user, waiting_for_approval, finished, inactivity, etc.\) | | `title` | string | Session title | -| `createdAt` | number | Creation timestamp \(Unix\) | -| `updatedAt` | number | Last updated timestamp \(Unix\) | -| `acusConsumed` | number | ACUs consumed | -| `tags` | json | Session tags | +| `createdAt` | number | Unix timestamp when the session was created | +| `updatedAt` | number | Unix timestamp when the session was last updated | +| `acusConsumed` | number | ACUs consumed by the session | +| `tags` | json | Tags associated with the session | | `pullRequests` | json | Pull requests created during the session | | `structuredOutput` | json | Structured output from the session | | `playbookId` | string | Associated playbook ID | -| `sessions` | json | List of sessions | diff --git a/apps/sim/tools/devin/create-session.ts b/apps/sim/tools/devin/create_session.ts similarity index 100% rename from apps/sim/tools/devin/create-session.ts rename to apps/sim/tools/devin/create_session.ts diff --git a/apps/sim/tools/devin/get-session.ts b/apps/sim/tools/devin/get_session.ts similarity index 100% rename from apps/sim/tools/devin/get-session.ts rename to apps/sim/tools/devin/get_session.ts diff --git a/apps/sim/tools/devin/index.ts b/apps/sim/tools/devin/index.ts index 91a2e42801b..be9d1f91db8 100644 --- a/apps/sim/tools/devin/index.ts +++ b/apps/sim/tools/devin/index.ts @@ -1,4 +1,4 @@ -export { devinCreateSessionTool } from './create-session' -export { devinGetSessionTool } from './get-session' -export { devinListSessionsTool } from './list-sessions' -export { devinSendMessageTool } from './send-message' +export { devinCreateSessionTool } from './create_session' +export { devinGetSessionTool } from './get_session' +export { devinListSessionsTool } from './list_sessions' +export { devinSendMessageTool } from './send_message' diff --git a/apps/sim/tools/devin/list-sessions.ts b/apps/sim/tools/devin/list_sessions.ts similarity index 100% rename from apps/sim/tools/devin/list-sessions.ts rename to apps/sim/tools/devin/list_sessions.ts diff --git a/apps/sim/tools/devin/send-message.ts b/apps/sim/tools/devin/send_message.ts similarity index 100% rename from apps/sim/tools/devin/send-message.ts rename to apps/sim/tools/devin/send_message.ts From ef296c4f284e1ce90b61e2b4e157ce2ae34ccc45 Mon Sep 17 00:00:00 2001 From: waleed Date: Thu, 26 Feb 2026 11:37:48 -0800 Subject: [PATCH 5/6] regen docs --- .../content/docs/en/tools/google_bigquery.mdx | 3 +- .../content/docs/en/tools/google_books.mdx | 3 +- .../content/docs/en/tools/google_tasks.mdx | 30 ++++- apps/sim/tools/devin/list_sessions.ts | 118 +++++++++--------- 4 files changed, 88 insertions(+), 66 deletions(-) diff --git a/apps/docs/content/docs/en/tools/google_bigquery.mdx b/apps/docs/content/docs/en/tools/google_bigquery.mdx index 4b31096c7a6..38cc4edaad7 100644 --- a/apps/docs/content/docs/en/tools/google_bigquery.mdx +++ b/apps/docs/content/docs/en/tools/google_bigquery.mdx @@ -5,7 +5,7 @@ description: Query, list, and insert data in Google BigQuery import { BlockInfoCard } from "@/components/ui/block-info-card" - @@ -16,6 +16,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" In Sim, the Google BigQuery integration allows your agents to query datasets, list tables, inspect schemas, and insert rows as part of automated workflows. This enables use cases such as automated reporting, data pipeline orchestration, real-time data ingestion, and analytics-driven decision making. By connecting Sim with BigQuery, your agents can pull insights from petabytes of data, write results back to tables, and keep your analytics workflows running without manual intervention. {/* MANUAL-CONTENT-END */} + ## Usage Instructions Connect to Google BigQuery to run SQL queries, list datasets and tables, get table metadata, and insert rows. diff --git a/apps/docs/content/docs/en/tools/google_books.mdx b/apps/docs/content/docs/en/tools/google_books.mdx index d23d424f8b0..8e817dbc0db 100644 --- a/apps/docs/content/docs/en/tools/google_books.mdx +++ b/apps/docs/content/docs/en/tools/google_books.mdx @@ -5,7 +5,7 @@ description: Search and retrieve book information import { BlockInfoCard } from "@/components/ui/block-info-card" - @@ -16,6 +16,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" In Sim, the Google Books integration allows your agents to search for books and retrieve volume details as part of automated workflows. This enables use cases such as content research, reading list curation, bibliographic data enrichment, ISBN lookups, and knowledge gathering from published works. By connecting Sim with Google Books, your agents can discover and analyze book metadata, filter by availability or format, and incorporate literary references into their outputs—all without manual research. {/* MANUAL-CONTENT-END */} + ## Usage Instructions Search for books using the Google Books API. Find volumes by title, author, ISBN, or keywords, and retrieve detailed information about specific books including descriptions, ratings, and publication details. diff --git a/apps/docs/content/docs/en/tools/google_tasks.mdx b/apps/docs/content/docs/en/tools/google_tasks.mdx index 9743de39795..745b04c1e52 100644 --- a/apps/docs/content/docs/en/tools/google_tasks.mdx +++ b/apps/docs/content/docs/en/tools/google_tasks.mdx @@ -5,7 +5,7 @@ description: Manage Google Tasks import { BlockInfoCard } from "@/components/ui/block-info-card" - @@ -16,6 +16,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" In Sim, the Google Tasks integration allows your agents to create, read, update, delete, and list tasks and task lists as part of automated workflows. This enables use cases such as automated task creation from incoming data, to-do list management based on workflow triggers, task status tracking, and deadline monitoring. By connecting Sim with Google Tasks, your agents can manage action items programmatically, keep teams organized, and ensure nothing falls through the cracks. {/* MANUAL-CONTENT-END */} + ## Usage Instructions Integrate Google Tasks into your workflow. Create, read, update, delete, and list tasks and task lists. @@ -81,7 +82,24 @@ List all tasks in a Google Tasks list | Parameter | Type | Description | | --------- | ---- | ----------- | -| `tasks` | json | Array of tasks with id, title, notes, status, due, updated, and more | +| `tasks` | array | List of tasks | +| ↳ `id` | string | Task identifier | +| ↳ `title` | string | Title of the task | +| ↳ `notes` | string | Notes/description for the task | +| ↳ `status` | string | Task status: "needsAction" or "completed" | +| ↳ `due` | string | Due date \(RFC 3339 timestamp\) | +| ↳ `completed` | string | Completion date \(RFC 3339 timestamp\) | +| ↳ `updated` | string | Last modification time \(RFC 3339 timestamp\) | +| ↳ `selfLink` | string | URL pointing to this task | +| ↳ `webViewLink` | string | Link to task in Google Tasks UI | +| ↳ `parent` | string | Parent task identifier | +| ↳ `position` | string | Position among sibling tasks \(string-based ordering\) | +| ↳ `hidden` | boolean | Whether the task is hidden | +| ↳ `deleted` | boolean | Whether the task is deleted | +| ↳ `links` | array | Collection of links associated with the task | +| ↳ `type` | string | Link type \(e.g., "email", "generic", "chat_message"\) | +| ↳ `description` | string | Link description | +| ↳ `link` | string | The URL | | `nextPageToken` | string | Token for retrieving the next page of results | ### `google_tasks_get` @@ -170,14 +188,18 @@ Retrieve all task lists for the authenticated user | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `maxResults` | number | No | Maximum number of task lists to return \(default 1000, max 1000\) | +| `maxResults` | number | No | Maximum number of task lists to return \(default 20, max 100\) | | `pageToken` | string | No | Token for pagination | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `taskLists` | json | Array of task lists with id, title, updated, and selfLink | +| `taskLists` | array | List of task lists | +| ↳ `id` | string | Task list identifier | +| ↳ `title` | string | Title of the task list | +| ↳ `updated` | string | Last modification time \(RFC 3339 timestamp\) | +| ↳ `selfLink` | string | URL pointing to this task list | | `nextPageToken` | string | Token for retrieving the next page of results | diff --git a/apps/sim/tools/devin/list_sessions.ts b/apps/sim/tools/devin/list_sessions.ts index 53129d1199e..fa066fdac11 100644 --- a/apps/sim/tools/devin/list_sessions.ts +++ b/apps/sim/tools/devin/list_sessions.ts @@ -2,71 +2,69 @@ import type { ToolConfig } from '@/tools/types' import type { DevinListSessionsParams, DevinListSessionsResponse } from './types' import { DEVIN_SESSION_LIST_ITEM_PROPERTIES } from './types' -export const devinListSessionsTool: ToolConfig< - DevinListSessionsParams, - DevinListSessionsResponse -> = { - id: 'devin_list_sessions', - name: 'list_sessions', - description: 'List Devin sessions in the organization. Returns up to 100 sessions by default.', - version: '1.0.0', +export const devinListSessionsTool: ToolConfig = + { + id: 'devin_list_sessions', + name: 'list_sessions', + description: 'List Devin sessions in the organization. Returns up to 100 sessions by default.', + version: '1.0.0', - params: { - apiKey: { - type: 'string', - required: true, - visibility: 'user-only', - description: 'Devin API key (service user credential starting with cog_)', - }, - limit: { - type: 'number', - required: false, - visibility: 'user-or-llm', - description: 'Maximum number of sessions to return (1-200, default: 100)', + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of sessions to return (1-200, default: 100)', + }, }, - }, - request: { - url: (params) => { - const searchParams = new URLSearchParams() - if (params.limit) searchParams.set('first', String(Number(params.limit))) - const qs = searchParams.toString() - return `https://api.devin.ai/v3/organizations/sessions${qs ? `?${qs}` : ''}` + request: { + url: (params) => { + const searchParams = new URLSearchParams() + if (params.limit) searchParams.set('first', String(Number(params.limit))) + const qs = searchParams.toString() + return `https://api.devin.ai/v3/organizations/sessions${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), }, - method: 'GET', - headers: (params) => ({ - Authorization: `Bearer ${params.apiKey}`, - }), - }, - transformResponse: async (response: Response) => { - const data = await response.json() - const items = data.items ?? [] - return { - success: true, - output: { - sessions: items.map((item: Record) => ({ - sessionId: item.session_id ?? null, - url: item.url ?? null, - status: item.status ?? null, - statusDetail: item.status_detail ?? null, - title: item.title ?? null, - createdAt: item.created_at ?? null, - updatedAt: item.updated_at ?? null, - tags: item.tags ?? null, - })), - }, - } - }, + transformResponse: async (response: Response) => { + const data = await response.json() + const items = data.items ?? [] + return { + success: true, + output: { + sessions: items.map((item: Record) => ({ + sessionId: item.session_id ?? null, + url: item.url ?? null, + status: item.status ?? null, + statusDetail: item.status_detail ?? null, + title: item.title ?? null, + createdAt: item.created_at ?? null, + updatedAt: item.updated_at ?? null, + tags: item.tags ?? null, + })), + }, + } + }, - outputs: { - sessions: { - type: 'array', - description: 'List of Devin sessions', - items: { - type: 'object', - properties: DEVIN_SESSION_LIST_ITEM_PROPERTIES, + outputs: { + sessions: { + type: 'array', + description: 'List of Devin sessions', + items: { + type: 'object', + properties: DEVIN_SESSION_LIST_ITEM_PROPERTIES, + }, }, }, - }, -} + } From fda98f59168105ba560258751e7fe52fd74a10ed Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Thu, 26 Feb 2026 11:47:13 -0800 Subject: [PATCH 6/6] fix(devin): remove redundant Number() conversions in tool request bodies --- apps/sim/tools/devin/create_session.ts | 4 ++-- apps/sim/tools/devin/list_sessions.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/sim/tools/devin/create_session.ts b/apps/sim/tools/devin/create_session.ts index 70be1c8b81b..1c99bfba774 100644 --- a/apps/sim/tools/devin/create_session.ts +++ b/apps/sim/tools/devin/create_session.ts @@ -57,8 +57,8 @@ export const devinCreateSessionTool: ToolConfig< prompt: params.prompt, } if (params.playbookId) body.playbook_id = params.playbookId - if (params.maxAcuLimit != null && params.maxAcuLimit !== '') { - body.max_acu_limit = Number(params.maxAcuLimit) + if (params.maxAcuLimit != null) { + body.max_acu_limit = params.maxAcuLimit } if (params.tags) { body.tags = params.tags.split(',').map((t: string) => t.trim()) diff --git a/apps/sim/tools/devin/list_sessions.ts b/apps/sim/tools/devin/list_sessions.ts index fa066fdac11..66391e4f34e 100644 --- a/apps/sim/tools/devin/list_sessions.ts +++ b/apps/sim/tools/devin/list_sessions.ts @@ -27,7 +27,7 @@ export const devinListSessionsTool: ToolConfig { const searchParams = new URLSearchParams() - if (params.limit) searchParams.set('first', String(Number(params.limit))) + if (params.limit) searchParams.set('first', String(params.limit)) const qs = searchParams.toString() return `https://api.devin.ai/v3/organizations/sessions${qs ? `?${qs}` : ''}` },