Skip to content

Commit 86ae98a

Browse files
committed
simplify dynamic tool calling vs static tool call choice by adding new promptConfig to subagent definition + modularize some common functions (useToolCallService + getPromptConfig)
1 parent c53d8a2 commit 86ae98a

4 files changed

Lines changed: 140 additions & 58 deletions

File tree

.gemini/settings.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,18 @@
1414
// "model": "gemma3n:e4b"
1515
"model": "gemma3:12b",
1616
// "model": "gemma3:12b"
17-
"subagentSummarizeToolOutput": { "enabled": true }
17+
"subagentSummarizeToolOutput": { "enabled": false }
1818
},
1919
"useModelRouter": {
2020
"useGemmaRouting": {
2121
"enabled": true,
22-
"host": "http://localhost:8000",
22+
// "host": "http://localhost:8000",
23+
"host": "http://localhost:11434",
2324
// "model": "gemma3n:e4b"
2425
// "model": "gemma3n:e2b"
2526
"model": "gemma3:1b",
26-
"provider": "litert-lm"
27+
// "provider": "litert-lm"
28+
"provider": "ollama"
2729
// "model": "gemma3:270m"
2830
}
2931
}

packages/core/src/agents/build-test-agent.ts

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ The user will provide you with an objective on building and/or testing code. You
7979
---
8080
## Available Tools
8181
You have access to these tools:
82-
\${tools_list}
82+
\${tool_code}
8383
---
8484
\${directive}
8585
`,
@@ -134,7 +134,7 @@ Now, handle the user message and tool call responses below:
134134
135135
## Available Tools
136136
You have access to these tools:
137-
\${tools_list}
137+
\${tool_code}
138138
139139
140140
Example for gathering information (\`glob\` or \`read_file\`) or executing a command (\`run_shell_command\`):
@@ -146,6 +146,99 @@ I need to [Your concise rationale and what you are trying to do and why it will
146146
}
147147
\`\`\`
148148
149+
Example for analyzing output and completing the task:
150+
I am satisfied with the results. Here are the execution highlights:
151+
- [Your concise highlights go here].
152+
- [Your concise highlights go here].
153+
- [Your concise highlights go here].
154+
- [Your concise highlights go here].
155+
- [Your concise highlights go here].
156+
\`\`\`json
157+
{
158+
"name": "complete_task"
159+
}
160+
\`\`\`
161+
`,
162+
},
163+
164+
promptConfigDynamicTools: {
165+
query: `Your task is to respond to the following user objective:
166+
<objective>
167+
\${objective}
168+
</objective>`,
169+
systemPrompt: `You are a **Build And Test Agent**, a hyper-specialized AI agent that builds and tests code in the current project. You are a sub-agent within a larger development system.
170+
The user will provide you with an objective on building and/or testing code. Your *SOLE PURPOSE* is to:
171+
1. Identify the correct build or test command for the project by inspecting the source code and project structure.
172+
2. Execute the build or test command.
173+
3. Analyze the output of the build or test command and report back to the main agent when the objective is met.
174+
---
175+
## Available Tools
176+
You have access to these tools:
177+
\${tool_code}
178+
---
179+
\${directive}
180+
`,
181+
directive: `## Directive
182+
You are a **Build And Test Agent**, a hyper-specialized AI agent that builds and tests code in the current project. You are a sub-agent within a larger development system.
183+
The user will provide you with an objective on building and/or testing code. Your *SOLE PURPOSE* is to:
184+
1. Identify the correct build or test command for the project.
185+
2. Execute the build or test command.
186+
3. Analyze the output of the build or test command and report back to the main agent when the objective is met.
187+
188+
**Information Gathering and Planning:**
189+
You must take as many steps as necessary to understand the project before running commands. You must first gather sufficient information about the project to identify the correct build or test command. Use the \`glob\` and \`read_file\` tools as many times as necessary to:
190+
- Identify files and their paths relevant to the user's objective.
191+
- Determine the project's build and testing environment (e.g., presence of package.json, pom.xml, CMakeLists.txt, setup.py, etc.).
192+
193+
**Execution:**
194+
Once you have identified the correct command, use the \`run_shell_command\` tool to execute the build or test.
195+
196+
**Analysis and Completion:**
197+
After executing a command, analyze its output.
198+
- If the output suggests the objective is not yet met (e.g., errors, incorrect command), you must go back to gathering information or refining the command.
199+
- If the command directly addresses the user's objective and you are satisfied with the result, you must highlight the most important findings to the user in no more than five bullet points and call the \`complete_task\` tool. Only report key information relevant to the user's objective (e.g., test names, file names, pass/fail status).
200+
201+
**Output Format:**
202+
Your response must *ONLY* contain a one-line explanation of your rationale, followed by the tool choice in JSON format.
203+
204+
**Tool Call Example (for gathering info or execution):**
205+
I need to [Your concise rationale and what you are trying to do and why it will help].
206+
\`\`\`json
207+
{
208+
"name": "tool_name"
209+
}
210+
\`\`\`
211+
212+
**Task Completion Example:**
213+
I am satisfied with the results. Here are the execution highlights:
214+
- [Your concise highlights go here].
215+
- [Your concise highlights go here].
216+
- [Your concise highlights go here].
217+
- [Your concise highlights go here].
218+
- [Your concise highlights go here].
219+
\`\`\`json
220+
{
221+
"name": "complete_task"
222+
}
223+
\`\`\`
224+
225+
Now, handle the user message and tool call responses below:
226+
`,
227+
reminder: `Remember! You are a **Build And Test Agent** whose purpose is to build and/or test code according to the user's objective.
228+
229+
## Available Tools
230+
You have access to these tools:
231+
\${tool_code}
232+
233+
234+
Example for gathering information (\`glob\` or \`read_file\`) or executing a command (\`run_shell_command\`):
235+
I need to [Your concise rationale and what you are trying to do and why it will help].
236+
\`\`\`json
237+
{
238+
"name": "tool_name"
239+
}
240+
\`\`\`
241+
149242
Example for analyzing output and completing the task:
150243
I am satisfied with the results. Here are the execution highlights:
151244
- [Your concise highlights go here].

packages/core/src/agents/executor.ts

Lines changed: 39 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,9 @@ export class AgentExecutor<TOutput extends z.ZodTypeAny> {
547547
signalManager.startAgentSession();
548548
chat = await this.createChatObject(inputs);
549549
tools = this.prepareToolsList();
550-
const query = this.definition.promptConfig.query
551-
? templateString(this.definition.promptConfig.query, inputs)
550+
const promptConfig = this._getPromptConfig();
551+
const query = promptConfig.query
552+
? templateString(promptConfig.query, inputs)
552553
: inputs['objective'] !== undefined
553554
? (inputs['objective'] as string)
554555
: 'Get Started!';
@@ -1079,7 +1080,8 @@ export class AgentExecutor<TOutput extends z.ZodTypeAny> {
10791080
private async createChatObject(
10801081
inputs: AgentInputs,
10811082
): Promise<GeminiChat | OllamaChat> {
1082-
const { promptConfig, modelConfig } = this.definition;
1083+
const { modelConfig } = this.definition;
1084+
const promptConfig = this._getPromptConfig();
10831085

10841086
if (!promptConfig.systemPrompt && !promptConfig.initialMessages) {
10851087
throw new Error(
@@ -1113,9 +1115,9 @@ export class AgentExecutor<TOutput extends z.ZodTypeAny> {
11131115
const populatedPromptConfig: PromptConfig = {
11141116
...promptConfig,
11151117
systemPrompt: this.systemInstruction ?? '',
1116-
directive: this.definition.promptConfig.directive,
1117-
query: this.definition.promptConfig.query
1118-
? templateString(this.definition.promptConfig.query, inputs)
1118+
directive: promptConfig.directive,
1119+
query: promptConfig.query
1120+
? templateString(promptConfig.query, inputs)
11191121
: 'Get Started!',
11201122
};
11211123
return new OllamaChat(
@@ -1173,19 +1175,7 @@ export class AgentExecutor<TOutput extends z.ZodTypeAny> {
11731175
submittedOutput: string | null;
11741176
taskCompleted: boolean;
11751177
}> {
1176-
const agentName = this.definition.name;
1177-
let useToolCallService = false;
1178-
if (agentName === 'codebase_investigator') {
1179-
useToolCallService =
1180-
!!this.runtimeContext.getCodebaseInvestigatorSettings()
1181-
.useToolCallService;
1182-
} else if (agentName === 'gemma_agent') {
1183-
useToolCallService =
1184-
!!this.runtimeContext.getGemmaSubagentSettings().useToolCallService;
1185-
} else if (agentName === 'build_and_test_agent') {
1186-
useToolCallService =
1187-
!!this.runtimeContext.getBuildAndTestSettings().useToolCallService;
1188-
}
1178+
const useToolCallService = this._usesToolCallService();
11891179

11901180
if (useToolCallService) {
11911181
const completeFunctionCalls: FunctionCall[] = [];
@@ -1647,9 +1637,34 @@ export class AgentExecutor<TOutput extends z.ZodTypeAny> {
16471637
)}`;
16481638
}
16491639

1640+
private _usesToolCallService(): boolean {
1641+
const agentName = this.definition.name;
1642+
if (agentName === 'codebase_investigator') {
1643+
return !!this.runtimeContext.getCodebaseInvestigatorSettings()
1644+
.useToolCallService;
1645+
} else if (agentName === 'gemma_agent') {
1646+
return !!this.runtimeContext.getGemmaSubagentSettings()
1647+
.useToolCallService;
1648+
} else if (agentName === 'build_and_test_agent') {
1649+
return !!this.runtimeContext.getBuildAndTestSettings().useToolCallService;
1650+
}
1651+
return false;
1652+
}
1653+
1654+
private _getPromptConfig(): PromptConfig {
1655+
const useToolCallService = this._usesToolCallService();
1656+
1657+
const promptConfig =
1658+
useToolCallService && this.definition.promptConfigDynamicTools
1659+
? this.definition.promptConfigDynamicTools
1660+
: this.definition.promptConfig;
1661+
1662+
return promptConfig;
1663+
}
1664+
16501665
/** Builds the system prompt from the agent definition and inputs. */
16511666
private async buildSystemPrompt(inputs: AgentInputs): Promise<string> {
1652-
const { promptConfig } = this.definition;
1667+
const promptConfig = this._getPromptConfig();
16531668
if (!promptConfig.systemPrompt) {
16541669
return '';
16551670
}
@@ -1660,45 +1675,16 @@ export class AgentExecutor<TOutput extends z.ZodTypeAny> {
16601675
templateInputs['directive'] = promptConfig.directive;
16611676
}
16621677

1663-
if (
1664-
promptConfig.systemPrompt.includes('${tool_code}') ||
1665-
promptConfig.systemPrompt.includes('${tools_list}')
1666-
) {
1678+
if (promptConfig.systemPrompt.includes('${tool_code}')) {
16671679
const tools = this.prepareToolsList();
1668-
let useToolCallService = false;
1669-
const agentName = this.definition.name;
1670-
if (agentName === 'codebase_investigator') {
1671-
useToolCallService =
1672-
!!this.runtimeContext.getCodebaseInvestigatorSettings()
1673-
.useToolCallService;
1674-
} else if (agentName === 'gemma_agent') {
1675-
useToolCallService =
1676-
!!this.runtimeContext.getGemmaSubagentSettings().useToolCallService;
1677-
} else if (agentName === 'build_and_test_agent') {
1678-
useToolCallService =
1679-
!!this.runtimeContext.getBuildAndTestSettings().useToolCallService;
1680-
}
1680+
const useToolCallService = this._usesToolCallService();
16811681

16821682
if (useToolCallService) {
16831683
const toolNames = tools.map((tool) => tool.name).join(', ');
1684-
templateInputs['tools_list'] = toolNames;
1685-
if (promptConfig.directive) {
1686-
const newDirective = promptConfig.directive
1687-
.replace(
1688-
/Your response must \*ONLY\* contain a one-line explanation of your rationale, followed by the tool call in JSON format\./,
1689-
'Your response must *ONLY* contain a one-line explanation of your rationale, followed by the tool choice in JSON format.',
1690-
)
1691-
.replace(
1692-
/\{[\s\S]*?\}/,
1693-
`{
1694-
"name": "tool_name"
1695-
}`,
1696-
);
1697-
templateInputs['directive'] = newDirective;
1698-
}
1684+
templateInputs['tool_code'] = toolNames;
16991685
} else {
17001686
const toolCode = this._prepareGemmaToolCode(tools);
1701-
templateInputs['tools_list'] = toolCode;
1687+
templateInputs['tool_code'] = toolCode;
17021688
if (promptConfig.directive) {
17031689
templateInputs['directive'] = promptConfig.directive;
17041690
}

packages/core/src/agents/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export interface AgentDefinition<TOutput extends z.ZodTypeAny = z.ZodUnknown> {
6363
displayName?: string;
6464
description: string;
6565
promptConfig: PromptConfig;
66+
promptConfigDynamicTools?: PromptConfig;
6667
modelConfig: ModelConfig | OllamaModelConfig;
6768
runConfig: RunConfig;
6869
toolConfig?: ToolConfig;

0 commit comments

Comments
 (0)