feat(core): add standardized lifecycle debug logging for agents

This commit is contained in:
mkorwel
2026-02-12 00:31:56 -06:00
parent ed32dcb179
commit 303d001251
3 changed files with 31 additions and 3 deletions
@@ -8,6 +8,7 @@ import { type Config } from '../config/config.js';
import { AgentHarness, type AgentHarnessOptions } from './harness.js';
import { type AgentDefinition, type LocalAgentDefinition } from './types.js';
import { MainAgentBehavior, SubagentBehavior } from './behavior.js';
import { debugLogger } from '../utils/debugLogger.js';
/**
* Factory for creating agent executors/harnesses.
@@ -32,6 +33,10 @@ export class AgentFactory {
behavior = new MainAgentBehavior(config, options.parentPromptId);
}
debugLogger.debug(
`[AgentFactory] Creating harness for agent: ${behavior.name} (agentId: ${behavior.agentId})`,
);
return new AgentHarness({
config,
behavior,
+12 -1
View File
@@ -38,6 +38,7 @@ import { promptIdContext } from '../utils/promptIdContext.js';
import { logRecoveryAttempt } from '../telemetry/loggers.js';
import { RecoveryAttemptEvent } from '../telemetry/types.js';
import { DeadlineTimer } from '../utils/deadlineTimer.js';
import { debugLogger } from '../utils/debugLogger.js';
import type { ToolRegistry } from '../tools/tool-registry.js';
@@ -158,7 +159,11 @@ export class MainAgentBehavior implements AgentBehavior {
this.agentId = `${parentPrefix}main-${randomIdPart}`;
}
async initialize(_toolRegistry: ToolRegistry) {}
async initialize(_toolRegistry: ToolRegistry) {
debugLogger.debug(
`[MainAgentBehavior] [${this.name}:${this.agentId}] Initialized`,
);
}
async getSystemInstruction() {
const systemMemory = this.config.getUserMemory();
@@ -340,6 +345,9 @@ export class SubagentBehavior implements AgentBehavior {
}
async initialize(toolRegistry: ToolRegistry) {
debugLogger.debug(
`[SubagentBehavior] [${this.name}:${this.agentId}] Initializing tool registry`,
);
const parentToolRegistry = this.config.getToolRegistry();
if (this.definition.toolConfig) {
for (const toolRef of this.definition.toolConfig.tools) {
@@ -479,6 +487,9 @@ export class SubagentBehavior implements AgentBehavior {
reason: AgentTerminateMode,
signal: AbortSignal,
): AsyncGenerator<ServerGeminiStreamEvent, boolean> {
debugLogger.debug(
`[SubagentBehavior] [${this.name}:${this.agentId}] Entering recovery mode. Reason: ${reason}`,
);
const recoveryStartTime = Date.now();
let success = false;
const graceTimeoutController = new DeadlineTimer(
+14 -2
View File
@@ -125,7 +125,7 @@ export class AgentHarness {
): AsyncGenerator<ServerGeminiStreamEvent, Turn> {
const startTime = Date.now();
debugLogger.debug(
`[AgentHarness] Starting unified ReAct loop for agent: ${this.behavior.name}`,
`[AgentHarness] [${this.behavior.name}:${this.behavior.agentId}] Starting unified ReAct loop`,
);
const maxTurnsLimit = maxTurns ?? DEFAULT_MAX_TURNS;
@@ -164,6 +164,10 @@ export class AgentHarness {
try {
while (this.turnCounter < maxTurnsLimit) {
const promptId = `${this.behavior.agentId}#${this.turnCounter}`;
debugLogger.debug(
`[AgentHarness] [${this.behavior.name}:${this.behavior.agentId}] Starting turn ${this.turnCounter} (promptId: ${promptId})`,
);
if (combinedSignal.aborted) {
terminateReason = deadlineTimer.signal.aborted
? AgentTerminateMode.TIMEOUT
@@ -370,12 +374,16 @@ export class AgentHarness {
}
} finally {
deadlineTimer.abort();
const duration = Date.now() - startTime;
debugLogger.debug(
`[AgentHarness] [${this.behavior.name}:${this.behavior.agentId}] Finished. Outcome: ${terminateReason}, Duration: ${duration}ms, Turns: ${this.turnCounter}`,
);
logAgentFinish(
this.config,
new AgentFinishEvent(
this.behavior.agentId,
this.behavior.name,
Date.now() - startTime,
duration,
this.turnCounter,
terminateReason,
),
@@ -426,6 +434,10 @@ export class AgentHarness {
);
const otherCalls = calls.filter((c) => c.name !== TASK_COMPLETE_TOOL_NAME);
debugLogger.debug(
`[AgentHarness] [${this.behavior.name}:${this.behavior.agentId}] Executing ${calls.length} tool calls (${otherCalls.length} scheduled)`,
);
let completedCalls: Array<{
request: ToolCallRequestInfo;
response: { responseParts: Part[] };