Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion agents/base2/base2.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { buildArray } from '@codebuff/common/util/array'
import { COMPOSIO_META_TOOL_NAMES } from '@codebuff/common/constants/composio'
import {
FREEBUFF_GEMINI_THINKER_AGENT_ID,
FREEBUFF_GEMINI_THINKER_INSTRUCTIONS_PROMPT,
Expand All @@ -17,6 +18,8 @@ import {
type SecretAgentDefinition,
} from '../types/secret-agent-definition'

const ENABLE_COMPOSIO_TOOLS = false

export function createBase2(
mode: 'default' | 'free' | 'lite' | 'max' | 'fast',
options?: {
Expand Down Expand Up @@ -105,6 +108,7 @@ export function createBase2(
'set_output',
'list_directory',
'glob',
ENABLE_COMPOSIO_TOOLS && COMPOSIO_META_TOOL_NAMES,
),
spawnableAgents: buildArray(
!isMax && 'file-picker',
Expand Down Expand Up @@ -148,7 +152,8 @@ Current date: ${PLACEHOLDER.CURRENT_DATE}.
}
- **Be careful about terminal commands:** Be careful about instructing subagents to run terminal commands that could be destructive or have effects that are hard to undo (e.g. git push, git commit, running any scripts -- especially ones that could alter production environments (!), installing packages globally, etc). Don't run any of these effectful commands unless the user explicitly asks you to.
- **Do what the user asks:** If the user asks you to do something, even running a risky terminal command, do it.
- **Don't use set_output:** The set_output tool is for spawned subagents to report results. Don't use it yourself.
- **Don't use set_output:** The set_output tool is for spawned subagents to report results. Don't use it yourself.${ENABLE_COMPOSIO_TOOLS ? `
- **External apps:** When Composio tools are available and the user asks to work with connected apps or services like Gmail, Google Calendar, GitHub, Slack, Linear, or Notion, use them to search for the right app tools, help the user connect their account, and execute the requested action.` : ''}

# Code Editing Mandates

Expand Down
8 changes: 6 additions & 2 deletions agents/types/secret-agent-definition.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { AgentDefinition } from './agent-definition'
import type * as Tools from './tools'
import type { ComposioMetaToolName } from '@codebuff/common/constants/composio'
export type { Tools }

export type AllToolNames =
Expand All @@ -9,9 +10,12 @@ export type AllToolNames =
| 'create_plan'
| 'spawn_agent_inline'
| 'update_subgoal'
| ComposioMetaToolName

export interface SecretAgentDefinition
extends Omit<AgentDefinition, 'toolNames'> {
export interface SecretAgentDefinition extends Omit<
AgentDefinition,
'toolNames'
> {
/** Tools this agent can use. */
toolNames?: AllToolNames[]
}
Expand Down
19 changes: 19 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions common/src/constants/composio.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export const COMPOSIO_API_KEY_ENV_VAR = 'COMPOSIO_API_KEY'

export const COMPOSIO_META_TOOL_NAMES = [
'composio_manage_connections',
'composio_multi_execute_tool',
'composio_search_tools',
'composio_get_tool_schemas',
] as const

export type ComposioMetaToolName = (typeof COMPOSIO_META_TOOL_NAMES)[number]

export const COMPOSIO_META_TOOL_NAME_TO_UPSTREAM = {
composio_manage_connections: 'COMPOSIO_MANAGE_CONNECTIONS',
composio_multi_execute_tool: 'COMPOSIO_MULTI_EXECUTE_TOOL',
composio_search_tools: 'COMPOSIO_SEARCH_TOOLS',
composio_get_tool_schemas: 'COMPOSIO_GET_TOOL_SCHEMAS',
} as const satisfies Record<ComposioMetaToolName, string>

export type ComposioUpstreamMetaToolName =
(typeof COMPOSIO_META_TOOL_NAME_TO_UPSTREAM)[ComposioMetaToolName]

const COMPOSIO_META_TOOL_NAME_SET = new Set<string>(COMPOSIO_META_TOOL_NAMES)

export function isComposioMetaToolName(
toolName: string,
): toolName is ComposioMetaToolName {
return COMPOSIO_META_TOOL_NAME_SET.has(toolName)
}

export function getComposioUpstreamToolName(
toolName: ComposioMetaToolName,
): ComposioUpstreamMetaToolName {
return COMPOSIO_META_TOOL_NAME_TO_UPSTREAM[toolName]
}
3 changes: 3 additions & 0 deletions common/src/tools/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { COMPOSIO_META_TOOL_NAMES } from '../constants/composio'

import type { ToolResultOutput } from '../types/messages/content-part'
import type { Tool } from 'ai'

Expand Down Expand Up @@ -56,6 +58,7 @@ export const toolNames = [
'web_search',
'write_file',
'write_todos',
...COMPOSIO_META_TOOL_NAMES,
] as const

export const publishedTools = [
Expand Down
20 changes: 19 additions & 1 deletion common/src/tools/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { applyPatchParams } from './params/tool/apply-patch'
import { askUserParams } from './params/tool/ask-user'
import { browserLogsParams } from './params/tool/browser-logs'
import { codeSearchParams } from './params/tool/code-search'
import { composioMetaToolParams } from './params/tool/composio'
import { createPlanParams } from './params/tool/create-plan'
import { endTurnParams } from './params/tool/end-turn'
import { findFilesParams } from './params/tool/find-files'
Expand Down Expand Up @@ -77,6 +78,7 @@ export const toolParams = {
web_search: webSearchParams,
write_file: writeFileParams,
write_todos: writeTodosParams,
...composioMetaToolParams,
} satisfies {
[K in ToolName]: $ToolParams<K>
}
Expand Down Expand Up @@ -151,6 +153,22 @@ export const clientToolCallSchema = z.discriminatedUnion('toolName', [
toolName: z.literal('write_file'),
input: FileChangeSchema,
}),
z.object({
toolName: z.literal('composio_manage_connections'),
input: toolParams.composio_manage_connections.inputSchema,
}),
z.object({
toolName: z.literal('composio_multi_execute_tool'),
input: toolParams.composio_multi_execute_tool.inputSchema,
}),
z.object({
toolName: z.literal('composio_search_tools'),
input: toolParams.composio_search_tools.inputSchema,
}),
z.object({
toolName: z.literal('composio_get_tool_schemas'),
input: toolParams.composio_get_tool_schemas.inputSchema,
}),
])
export const clientToolNames = clientToolCallSchema.def.options.map(
(opt) => opt.shape.toolName.value,
Expand All @@ -163,4 +181,4 @@ export type ClientToolCall<T extends ClientToolName = ClientToolName> = Extract<
> &
Pick<ToolCallPart, 'toolCallId' | 'toolName' | 'input' | 'providerOptions'>

export type PublishedClientToolName = ClientToolName & PublishedToolName
export type PublishedClientToolName = Extract<ClientToolName, PublishedToolName>
131 changes: 131 additions & 0 deletions common/src/tools/params/tool/composio.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { COMPOSIO_META_TOOL_NAMES } from '../../../constants/composio'
import z from 'zod/v4'

import { jsonToolResultSchema } from '../utils'

import type { $ToolParams } from '../../constants'

const sessionIdParam = z
.string()
.optional()
.describe('Session ID returned by composio_search_tools, when available.')

const composioMetaToolInputSchemas = {
composio_search_tools: z
.object({
queries: z
.array(z.unknown())
.min(1)
.describe(
'Structured English search queries. Split independent app/API actions into separate queries.',
),
session: z
.object({
generate_id: z.boolean().optional(),
id: z.string().optional(),
})
.catchall(z.unknown())
.describe(
'Use { generate_id: true } for a new workflow, or { id } to continue one.',
),
model: z.string().optional().describe('Client LLM model name.'),
})
.catchall(z.unknown()),
composio_get_tool_schemas: z
.object({
tool_slugs: z
.array(z.string())
.min(1)
.describe('Composio tool slugs to retrieve schemas for.'),
include: z
.array(z.string())
.optional()
.describe('Schema fields to include, e.g. input_schema/output_schema.'),
session_id: sessionIdParam,
})
.catchall(z.unknown()),
composio_manage_connections: z
.object({
toolkits: z
.array(z.string())
.min(1)
.describe('Toolkit slugs to check or connect, such as gmail/github.'),
reinitiate_all: z
.boolean()
.optional()
.describe('Force reconnection even if active credentials exist.'),
session_id: sessionIdParam,
})
.catchall(z.unknown()),
composio_multi_execute_tool: z
.object({
tools: z
.array(z.record(z.string(), z.unknown()))
.min(1)
.describe('Logically independent Composio tools to execute.'),
thought: z
.string()
.optional()
.describe('One concise sentence explaining the execution intent.'),
sync_response_to_workbench: z
.boolean()
.default(false)
.describe('Always use false. Codebuff disables Composio workbench.'),
session_id: sessionIdParam,
})
.catchall(z.unknown()),
}

const composioMetaToolDescriptions = {
composio_search_tools:
'Discover relevant Composio tools across external apps. Use this first for requests involving services like Gmail, GitHub, Slack, Linear, Notion, Google Calendar, or Google Sheets.',
composio_get_tool_schemas:
'Retrieve complete input schemas for specific Composio tool slugs returned by composio_search_tools.',
composio_manage_connections:
'Check or initiate user authentication for external app toolkits. Use when search/execution indicates a toolkit is not connected.',
composio_multi_execute_tool:
'Execute one or more discovered Composio app tools in the current workflow session. Do not use workbench offloading.',
}

const composioOutputSchema = jsonToolResultSchema(
z.union([
z.json(),
z.object({
errorMessage: z.string(),
status: z.number().optional(),
}),
]),
)

export const composioMetaToolParams = {
composio_manage_connections: {
toolName: 'composio_manage_connections',
endsAgentStep: true,
description: composioMetaToolDescriptions.composio_manage_connections,
inputSchema: composioMetaToolInputSchemas.composio_manage_connections,
outputSchema: composioOutputSchema,
},
composio_multi_execute_tool: {
toolName: 'composio_multi_execute_tool',
endsAgentStep: true,
description: composioMetaToolDescriptions.composio_multi_execute_tool,
inputSchema: composioMetaToolInputSchemas.composio_multi_execute_tool,
outputSchema: composioOutputSchema,
},
composio_search_tools: {
toolName: 'composio_search_tools',
endsAgentStep: true,
description: composioMetaToolDescriptions.composio_search_tools,
inputSchema: composioMetaToolInputSchemas.composio_search_tools,
outputSchema: composioOutputSchema,
},
composio_get_tool_schemas: {
toolName: 'composio_get_tool_schemas',
endsAgentStep: true,
description: composioMetaToolDescriptions.composio_get_tool_schemas,
inputSchema: composioMetaToolInputSchemas.composio_get_tool_schemas,
outputSchema: composioOutputSchema,
},
} satisfies {
[K in (typeof COMPOSIO_META_TOOL_NAMES)[number]]: $ToolParams<K>
}
16 changes: 13 additions & 3 deletions packages/agent-runtime/src/tools/handlers/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import { handleApplyPatch } from './tool/apply-patch'
import { handleAskUser } from './tool/ask-user'
import { handleBrowserLogs } from './tool/browser-logs'
import { handleCodeSearch } from './tool/code-search'
import {
handleComposioGetToolSchemas,
handleComposioManageConnections,
handleComposioMultiExecute,
handleComposioSearchTools,
} from './tool/composio'
import { handleCreatePlan } from './tool/create-plan'
import { handleEndTurn } from './tool/end-turn'
import { handleFindFiles } from './tool/find-files'
Expand Down Expand Up @@ -46,13 +52,19 @@ import type { ToolName } from '@codebuff/common/tools/constants'
* - Any additional arguments for the tool
* - Returns a promise that will be awaited
*/
export const codebuffToolHandlers = {
export const codebuffToolHandlers: {
[K in ToolName]: CodebuffToolHandlerFunction<K>
} = {
add_message: handleAddMessage,
add_subgoal: handleAddSubgoal,
apply_patch: handleApplyPatch,
ask_user: handleAskUser,
browser_logs: handleBrowserLogs,
code_search: handleCodeSearch,
composio_manage_connections: handleComposioManageConnections,
composio_multi_execute_tool: handleComposioMultiExecute,
composio_search_tools: handleComposioSearchTools,
composio_get_tool_schemas: handleComposioGetToolSchemas,
create_plan: handleCreatePlan,
end_turn: handleEndTurn,
find_files: handleFindFiles,
Expand Down Expand Up @@ -82,6 +94,4 @@ export const codebuffToolHandlers = {
web_search: handleWebSearch,
write_file: handleWriteFile,
write_todos: handleWriteTodos,
} satisfies {
[K in ToolName]: CodebuffToolHandlerFunction<K>
}
Loading
Loading