feat(sdk): Implement dynamic system instructions (#18863)

Co-authored-by: N. Taylor Mullen <ntaylormullen@google.com>
This commit is contained in:
Michael Bleigh
2026-02-13 12:48:35 -08:00
committed by GitHub
parent f460ab841d
commit f76e24c00f
6 changed files with 258 additions and 7 deletions
+36 -2
View File
@@ -24,8 +24,12 @@ import { SdkAgentFilesystem } from './fs.js';
import { SdkAgentShell } from './shell.js';
import type { SessionContext } from './types.js';
export type SystemInstructions =
| string
| ((context: SessionContext) => string | Promise<string>);
export interface GeminiCliAgentOptions {
instructions: string;
instructions: SystemInstructions;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
tools?: Array<Tool<any>>;
model?: string;
@@ -39,18 +43,24 @@ export class GeminiCliAgent {
private config: Config;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private tools: Array<Tool<any>>;
private readonly instructions: SystemInstructions;
private instructionsLoaded = false;
constructor(options: GeminiCliAgentOptions) {
this.instructions = options.instructions;
const cwd = options.cwd || process.cwd();
this.tools = options.tools || [];
const initialMemory =
typeof this.instructions === 'string' ? this.instructions : '';
const configParams: ConfigParameters = {
sessionId: `sdk-${Date.now()}`,
targetDir: cwd,
cwd,
debugMode: options.debug ?? false,
model: options.model || PREVIEW_GEMINI_MODEL_AUTO,
userMemory: options.instructions,
userMemory: initialMemory,
// Minimal config
enableHooks: false,
mcpEnabled: false,
@@ -94,6 +104,30 @@ export class GeminiCliAgent {
{ text: prompt },
];
if (!this.instructionsLoaded && typeof this.instructions === 'function') {
const context: SessionContext = {
sessionId,
transcript: client.getHistory(),
cwd: this.config.getWorkingDir(),
timestamp: new Date().toISOString(),
fs,
shell,
agent: this,
};
try {
const newInstructions = await this.instructions(context);
this.config.setUserMemory(newInstructions);
client.updateSystemInstruction();
this.instructionsLoaded = true;
} catch (e) {
const error =
e instanceof Error
? e
: new Error(`Error resolving dynamic instructions: ${String(e)}`);
throw error;
}
}
while (true) {
// sendMessageStream returns AsyncGenerator<ServerGeminiStreamEvent, Turn>
const stream = client.sendMessageStream(request, abortSignal, sessionId);