systemPrompt.ts
utils/systemPrompt.ts
No strong subsystem tag
124
Lines
4867
Bytes
3
Exports
8
Imports
10
Keywords
What this is
This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.
Beginner explanation
This file is one piece of the larger system. Its name, directory, imports, and exports show where it fits. Start by reading the exports and related files first.
How it is used
Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.
Expert explanation
Architecturally, this file intersects with general runtime concerns. It contains 124 lines, 8 detected imports, and 3 detected exports.
Important relationships
Detected exports
buildEffectiveSystemPromptasSystemPrompttype SystemPrompt
Keywords
promptmainthreadagentdefinitionproactiveagentappendsystempromptfeaturetoolusecontextassystempromptmodesystem
Detected imports
bun:bundle../services/analytics/index.js../Tool.js../tools/AgentTool/loadAgentsDir.js../tools/AgentTool/loadAgentsDir.js./envUtils.js./systemPromptType.js./systemPromptType.js
Source notes
This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.
Full source
import { feature } from 'bun:bundle'
import {
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
logEvent,
} from '../services/analytics/index.js'
import type { ToolUseContext } from '../Tool.js'
import type { AgentDefinition } from '../tools/AgentTool/loadAgentsDir.js'
import { isBuiltInAgent } from '../tools/AgentTool/loadAgentsDir.js'
import { isEnvTruthy } from './envUtils.js'
import { asSystemPrompt, type SystemPrompt } from './systemPromptType.js'
export { asSystemPrompt, type SystemPrompt } from './systemPromptType.js'
// Dead code elimination: conditional import for proactive mode.
// Same pattern as prompts.ts — lazy require to avoid pulling the module
// into non-proactive builds.
/* eslint-disable @typescript-eslint/no-require-imports */
const proactiveModule =
feature('PROACTIVE') || feature('KAIROS')
? (require('../proactive/index.js') as typeof import('../proactive/index.js'))
: null
/* eslint-enable @typescript-eslint/no-require-imports */
function isProactiveActive_SAFE_TO_CALL_ANYWHERE(): boolean {
return proactiveModule?.isProactiveActive() ?? false
}
/**
* Builds the effective system prompt array based on priority:
* 0. Override system prompt (if set, e.g., via loop mode - REPLACES all other prompts)
* 1. Coordinator system prompt (if coordinator mode is active)
* 2. Agent system prompt (if mainThreadAgentDefinition is set)
* - In proactive mode: agent prompt is APPENDED to default (agent adds domain
* instructions on top of the autonomous agent prompt, like teammates do)
* - Otherwise: agent prompt REPLACES default
* 3. Custom system prompt (if specified via --system-prompt)
* 4. Default system prompt (the standard Claude Code prompt)
*
* Plus appendSystemPrompt is always added at the end if specified (except when override is set).
*/
export function buildEffectiveSystemPrompt({
mainThreadAgentDefinition,
toolUseContext,
customSystemPrompt,
defaultSystemPrompt,
appendSystemPrompt,
overrideSystemPrompt,
}: {
mainThreadAgentDefinition: AgentDefinition | undefined
toolUseContext: Pick<ToolUseContext, 'options'>
customSystemPrompt: string | undefined
defaultSystemPrompt: string[]
appendSystemPrompt: string | undefined
overrideSystemPrompt?: string | null
}): SystemPrompt {
if (overrideSystemPrompt) {
return asSystemPrompt([overrideSystemPrompt])
}
// Coordinator mode: use coordinator prompt instead of default
// Use inline env check instead of coordinatorModule to avoid circular
// dependency issues during test module loading.
if (
feature('COORDINATOR_MODE') &&
isEnvTruthy(process.env.CLAUDE_CODE_COORDINATOR_MODE) &&
!mainThreadAgentDefinition
) {
// Lazy require to avoid circular dependency at module load time
const { getCoordinatorSystemPrompt } =
// eslint-disable-next-line @typescript-eslint/no-require-imports
require('../coordinator/coordinatorMode.js') as typeof import('../coordinator/coordinatorMode.js')
return asSystemPrompt([
getCoordinatorSystemPrompt(),
...(appendSystemPrompt ? [appendSystemPrompt] : []),
])
}
const agentSystemPrompt = mainThreadAgentDefinition
? isBuiltInAgent(mainThreadAgentDefinition)
? mainThreadAgentDefinition.getSystemPrompt({
toolUseContext: { options: toolUseContext.options },
})
: mainThreadAgentDefinition.getSystemPrompt()
: undefined
// Log agent memory loaded event for main loop agents
if (mainThreadAgentDefinition?.memory) {
logEvent('tengu_agent_memory_loaded', {
...(process.env.USER_TYPE === 'ant' && {
agent_type:
mainThreadAgentDefinition.agentType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
}),
scope:
mainThreadAgentDefinition.memory as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
source:
'main-thread' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
})
}
// In proactive mode, agent instructions are appended to the default prompt
// rather than replacing it. The proactive default prompt is already lean
// (autonomous agent identity + memory + env + proactive section), and agents
// add domain-specific behavior on top — same pattern as teammates.
if (
agentSystemPrompt &&
(feature('PROACTIVE') || feature('KAIROS')) &&
isProactiveActive_SAFE_TO_CALL_ANYWHERE()
) {
return asSystemPrompt([
...defaultSystemPrompt,
`\n# Custom Agent Instructions\n${agentSystemPrompt}`,
...(appendSystemPrompt ? [appendSystemPrompt] : []),
])
}
return asSystemPrompt([
...(agentSystemPrompt
? [agentSystemPrompt]
: customSystemPrompt
? [customSystemPrompt]
: defaultSystemPrompt),
...(appendSystemPrompt ? [appendSystemPrompt] : []),
])
}