- input-filter: scan workspace for SOUL.md, IDENTITY.md, MEMORY.md etc. on each turn - bootstrap: when these files exist, instruct Claude to Read them at session start - This gives the contractor agent its OpenClaw persona (SOUL.md embody, IDENTITY.md fill) - Memory note added to bootstrap when workspace has memory files Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
88 lines
3.7 KiB
TypeScript
88 lines
3.7 KiB
TypeScript
export type BootstrapInput = {
|
|
agentId: string;
|
|
openclawSessionKey: string;
|
|
workspace: string;
|
|
/** Skills XML block extracted from the OpenClaw system prompt, if any */
|
|
skillsBlock?: string;
|
|
/** Subset of OpenClaw context files present in the workspace (for persona/identity) */
|
|
workspaceContextFiles?: string[];
|
|
};
|
|
|
|
/**
|
|
* Build the one-time bootstrap message injected at the start of a new Claude session.
|
|
* This tells Claude it is operating as an OpenClaw contractor agent.
|
|
* Must NOT be re-injected on every turn.
|
|
*/
|
|
export function buildBootstrap(input: BootstrapInput): string {
|
|
const contextFiles = input.workspaceContextFiles ?? [];
|
|
const hasSoul = contextFiles.includes("SOUL.md");
|
|
const hasIdentity = contextFiles.includes("IDENTITY.md");
|
|
|
|
const lines = [
|
|
`You are operating as a contractor agent inside OpenClaw.`,
|
|
``,
|
|
`## Context`,
|
|
`- Agent ID: ${input.agentId}`,
|
|
`- Session key: ${input.openclawSessionKey}`,
|
|
`- Workspace: ${input.workspace}`,
|
|
``,
|
|
`## Role`,
|
|
`You receive tasks from OpenClaw users and complete them using your tools.`,
|
|
`You do not need to manage your own session context — OpenClaw handles session routing.`,
|
|
`Your responses go directly back to the user through OpenClaw.`,
|
|
``,
|
|
`## Guidelines`,
|
|
`- Work in the specified workspace directory.`,
|
|
`- Be concise and action-oriented. Use tools to accomplish tasks rather than describing what you would do.`,
|
|
`- Each message you receive contains the latest user request. Previous context is in your session memory.`,
|
|
`- If a task is unclear, ask one focused clarifying question.`,
|
|
];
|
|
|
|
// Inject persona/identity context from OpenClaw workspace files.
|
|
// These files define who this agent is and how it should behave.
|
|
if (hasSoul || hasIdentity) {
|
|
lines.push(``, `## Persona & Identity`);
|
|
if (hasSoul) {
|
|
lines.push(
|
|
`Read ${input.workspace}/SOUL.md now (using the Read tool) and embody the persona and tone it describes.`,
|
|
`SOUL.md defines your values, communication style, and boundaries — treat it as authoritative.`,
|
|
);
|
|
}
|
|
if (hasIdentity) {
|
|
lines.push(
|
|
`Read ${input.workspace}/IDENTITY.md now (using the Read tool) to understand your name, creature type, and personal vibe.`,
|
|
`If IDENTITY.md is empty/template-only, you may fill it in as you develop your identity.`,
|
|
);
|
|
}
|
|
}
|
|
|
|
// Memory system note: OpenClaw uses workspace/memory/*.md + MEMORY.md.
|
|
// Claude Code also maintains per-project auto-memory at ~/.claude/projects/<path>/memory/.
|
|
// Both are active; Claude Code's auto-memory is loaded automatically each session.
|
|
// OpenClaw memory tools (memory_search, memory_get) are available as MCP tools
|
|
// but require bridge-side implementations to execute (not yet wired).
|
|
if (contextFiles.includes("MEMORY.md") || contextFiles.some(f => f.startsWith("memory/"))) {
|
|
lines.push(
|
|
``,
|
|
`## Memory`,
|
|
`OpenClaw memory files exist in ${input.workspace}/memory/ and ${input.workspace}/MEMORY.md.`,
|
|
`Use the Read tool to access these directly. For writing new memories, write to ${input.workspace}/memory/<topic>.md.`,
|
|
);
|
|
}
|
|
|
|
if (input.skillsBlock) {
|
|
lines.push(
|
|
``,
|
|
`## Skills`,
|
|
`The following skills are available. When a task matches a skill's description:`,
|
|
`1. Read the skill's SKILL.md using the Read tool (the <location> field is the absolute path).`,
|
|
`2. Follow the instructions in SKILL.md. Replace \`{baseDir}\` with the directory containing SKILL.md.`,
|
|
`3. Run scripts using the Bash tool, NOT the \`exec\` tool (you have Bash, not exec).`,
|
|
``,
|
|
input.skillsBlock,
|
|
);
|
|
}
|
|
|
|
return lines.join("\n");
|
|
}
|