{"slug": "system-prompt-extraction-from-identity-files", "title": "System Prompt Extraction from Identity Files", "summary": "Signet's system prompt is being moved from AGENTS.md to the session-start hook to fix invisibility, identity pollution, and duplication issues. The new design injects a tool-focused briefing at every session, ensuring updates take effect immediately without reinstalling connectors.", "body_md": "# System Prompt Extraction from Identity Files\n\n*The Signet system prompt should be infrastructure, not content.*\n\n## Problem\n\nToday the Signet system prompt lives inside a `<!-- SIGNET:START -->`\n\n/\n`<!-- SIGNET:END -->`\n\nblock that gets injected into `AGENTS.md`\n\n(and\nits harness-specific copies like `CLAUDE.md`\n\n). This has three problems:\n\n### 1. The prompt is invisible to users who already have an AGENTS.md\n\nThe Signet block is injected when `AGENTS.md`\n\nis generated from\nscratch during setup. If a user already has an `AGENTS.md`\n\n— either\nhand-written or from a previous version of Signet — the system prompt\nis never re-inserted. The user’s agent runs without Signet’s tool\ninstructions, memory context, or identity stewardship guidelines.\n\nThe connector’s `install()`\n\nmethod calls `buildSignetBlock()`\n\nand\nwrites it into the generated file, but it won’t overwrite an existing\nfile. And even if it did, users would rightly object to their\nhand-crafted instructions being clobbered by auto-generated plumbing.\n\n### 2. The prompt pollutes the identity layer\n\n`AGENTS.md`\n\nis supposed to be the agent’s operating instructions —\n*how* it works, *what* it should do. The Signet system prompt is\ninfrastructure: tool availability, memory commands, file locations,\narchitecture explanations. Mixing the two makes both harder to\nmaintain and harder for models to parse. The user’s intent gets buried\nunder Signet’s self-description.\n\n### 3. The prompt is duplicated and scattered\n\nThe system prompt content is defined in `@signet/core`\n\n’s\n`buildSignetBlock()`\n\n, but each connector has its own copy/paste\ninstallation path. Updates to the prompt require rebuilding and\nreinstalling connectors. The `SIGNET-ARCHITECTURE.md`\n\nfile is a\nseparate artifact that duplicates some of the same information.\nThere’s no single source of truth that all connectors read at runtime.\n\n## Design\n\n### Move the system prompt to session-start hook output\n\nThe session-start hook already returns an `inject`\n\nstring that gets\nprepended to the model’s context. This is the natural place for the\nSignet system prompt. The hook runs on every session, regardless of\nwhat’s in `AGENTS.md`\n\n, and it’s controlled by the daemon — so updates\ntake effect immediately without reinstalling connectors.\n\n```\nCurrent flow:\n  AGENTS.md (contains Signet block) → symlinked to CLAUDE.md → model reads it\n  Session-start hook → returns memories + date/time → prepended to context\n\nProposed flow:\n  AGENTS.md (user content only) → symlinked to CLAUDE.md → model reads it\n  Session-start hook → returns system prompt + memories + date/time → prepended to context\n```\n\n### What the system prompt should contain\n\nThe prompt should be short, tool-focused, and avoid duplicating what models already know. It’s not an architecture document — it’s a briefing.\n\nProposed structure:\n\n```\n[signet active]\n\nYou have persistent memory managed by Signet. Your primary tool for\nretrieving memory is:\n\n  mcp__signet__memory_search — hybrid vector + keyword search across\n  all stored memories. Returns scored results with content, type, tags,\n  and entity graph context.\n\nFor deeper exploration:\n\n  mcp__signet__lcm_expand — drill into a session summary node.\n  Returns parent/child lineage, linked memories, and optionally the\n  cleaned transcript. Use this when memory_search returns a session\n  reference you want to expand.\n\n  mcp__signet__knowledge_expand — drill into an entity's aspects,\n  attributes, constraints, and dependencies.\n\n  mcp__signet__knowledge_expand_session — find session summaries\n  linked to a specific entity.\n\nCross-session history is also available through linked summary and\ntranscript artifacts in the Signet workspace. Inspect those artifacts\ndirectly when MEMORY.md or recall snippets are not enough.\n\nTo store a memory explicitly:\n\n  mcp__signet__memory_store — write a memory with content, type,\n  and optional tags.\n\nYour identity files are in your Signet workspace:\n  AGENTS.md — how you operate (you maintain this)\n  SOUL.md — your personality and values (you maintain this)\n  IDENTITY.md — who you are (you maintain this)\n  USER.md — who the user is (you maintain this)\n  MEMORY.md — auto-generated working memory summary (system-managed)\n\nSecrets are available via mcp__signet__secret_list and\nmcp__signet__secret_exec. Secrets are injected as environment\nvariables into subprocesses, never exposed as raw values.\n```\n\nThis is ~1200 chars. It tells the model what tools exist, what they do, and how to use them. No architecture lectures, no philosophy about memory layers, no instructions about “durable substrate.” Models are smart enough to figure out usage patterns from the tool descriptions themselves.\n\n### What gets removed from AGENTS.md\n\nThe entire `<!-- SIGNET:START -->`\n\n/ `<!-- SIGNET:END -->`\n\nblock is\nremoved from `buildSignetBlock()`\n\nin `@signet/core/src/markdown.ts`\n\n.\nThe function either returns an empty string or is removed entirely.\n\n`SIGNET-ARCHITECTURE.md`\n\nstays as an on-demand reference file — the\nsystem prompt doesn’t need to mention it. If a model or user wants to\nunderstand the pipeline internals, they can read it directly.\n\n### What changes in the session-start hook\n\n`handleSessionStart()`\n\nin `platform/daemon/src/hooks.ts`\n\nalready\nbuilds an `inject`\n\nstring from memories, date/time, and metadata.\nThe system prompt becomes the first section of that inject string,\nbefore memories and other context.\n\nThe system prompt is built at runtime by the daemon (not baked into connector configs), so it’s always current. If tools are added or renamed, the prompt updates on next session start.\n\n### What changes in connectors\n\nConnectors no longer inject `buildSignetBlock()`\n\ninto generated\nmarkdown files. The `install()`\n\nmethods still create/symlink\n`AGENTS.md`\n\n→ `CLAUDE.md`\n\netc., but only with the user’s content.\n\nFor existing users who already have a Signet block in their\n`AGENTS.md`\n\n, `signet install`\n\nstrips it on upgrade (remove content\nbetween `SIGNET:START`\n\nand `SIGNET:END`\n\nmarkers) as a marker-bounded,\nidempotent migration.\n\n## Migration Path\n\n### New users\n\nSetup wizard creates `AGENTS.md`\n\nwith only user-authored content (or\na minimal template). No Signet block. System prompt comes from the\nsession-start hook.\n\n### Existing users\n\nActive migration is required in this phase:\n\n`signet install`\n\ndetects`SIGNET:START`\n\n/`SIGNET:END`\n\nmarkers and strips the legacy block from workspace`AGENTS.md`\n\n.- The cleanup is marker-bounded and idempotent, preserving all user-authored content outside the block.\n- Session-start inject supplies the runtime system prompt on every new session, so users do not need to regenerate identity files.\n\n## Tool Naming\n\nThe current tool names (`mcp__signet__memory_search`\n\n,\n`mcp__signet__lcm_expand`\n\n, etc.) are functional but not discoverable.\nThe system prompt extraction is an opportunity to establish clearer\nnames or at least clear descriptions.\n\nCandidates for renaming (non-blocking, can be done separately):\n\n| Current | Candidate |\n|---|---|\n`mcp__signet__lcm_expand` | `mcp__signet__session_expand` |\n`mcp__signet__knowledge_expand` | `mcp__signet__entity_expand` |\n`mcp__signet__knowledge_expand_session` | `mcp__signet__entity_sessions` |\n\nThese are MCP tool names so renaming has compatibility implications. Could be done as aliases first, deprecating the old names.\n\n## Files to Modify\n\n| File | Change |\n|---|---|\n`platform/core/src/markdown.ts` | Remove or empty `buildSignetBlock()` . Keep `SIGNET_BLOCK_START` /`END` constants for migration detection. |\n`platform/daemon/src/hooks.ts` | Add system prompt to `handleSessionStart()` inject output |\n`integrations/claude-code/connector/src/index.ts` | Stop injecting Signet block into generated files. Optionally strip existing blocks on install. |\n`integrations/opencode/connector/src/index.ts` | Same as above |\n`integrations/openclaw/connector/src/index.ts` | Same as above |\n`integrations/codex/connector/src/index.ts` | Same as above |\n`integrations/oh-my-pi/connector/src/index.ts` | Apply the same legacy block cleanup during install |\n`platform/daemon-rs/crates/signet-daemon/src/routes/hooks.rs` | Mirror session-start system prompt injection to keep shadow parity |\n\n## Implementation Decisions (This Phase)\n\n**Character budget:** accepted for MVP. The injected system prompt is compact and fits inside existing session-start budgets.**Per-harness variation:** deferred. This phase uses one shared prompt across harnesses.**User override flag:** deferred. No suppression toggle in this phase.**Tool availability detection:** deferred. Prompt currently lists the canonical Signet MCP tools unconditionally.", "url": "https://wpnews.pro/news/system-prompt-extraction-from-identity-files", "canonical_source": "https://signetai.sh/docs/specs/approved/system-prompt-extraction/", "published_at": "2026-06-20 17:49:17+00:00", "updated_at": "2026-06-20 18:12:05.927560+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "ai-infrastructure", "ai-agents"], "entities": ["Signet", "AGENTS.md", "CLAUDE.md", "SIGNET-ARCHITECTURE.md", "MCP", "memory_search", "lcm_expand", "knowledge_expand"], "alternates": {"html": "https://wpnews.pro/news/system-prompt-extraction-from-identity-files", "markdown": "https://wpnews.pro/news/system-prompt-extraction-from-identity-files.md", "text": "https://wpnews.pro/news/system-prompt-extraction-from-identity-files.txt", "jsonld": "https://wpnews.pro/news/system-prompt-extraction-from-identity-files.jsonld"}}