@agentprojectcontext/apx 1.33.1 → 1.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/package.json +1 -1
  2. package/skills/apx/SKILL.md +49 -61
  3. package/src/core/agent/a2a/reply.js +48 -0
  4. package/src/core/agent/build-agent-system.js +136 -59
  5. package/src/core/agent/channels/voice-context.js +98 -0
  6. package/src/core/agent/memory.js +2 -1
  7. package/src/core/agent/prompt-builder.js +178 -124
  8. package/src/core/agent/prompts/channels/code.md +12 -10
  9. package/src/core/agent/prompts/channels/desktop.md +5 -32
  10. package/src/core/agent/prompts/channels/telegram.md +4 -15
  11. package/src/core/agent/prompts/channels/web_code.md +11 -11
  12. package/src/core/agent/prompts/core/agent-base.md +24 -0
  13. package/src/core/agent/prompts/core/project-agent.md +11 -0
  14. package/src/core/agent/prompts/core/super-agent.md +21 -0
  15. package/src/core/agent/prompts/discipline/action.md +10 -0
  16. package/src/core/agent/prompts/discipline/single-segment.md +6 -0
  17. package/src/core/agent/prompts/discipline/two-segment.md +11 -0
  18. package/src/core/agent/prompts/modes/code-build.md +1 -0
  19. package/src/core/agent/prompts/modes/code-plan.md +1 -0
  20. package/src/core/agent/prompts/modes/index.js +28 -0
  21. package/src/core/agent/self-memory.js +43 -1
  22. package/src/core/agent/skills/index-store.js +307 -0
  23. package/src/core/agent/skills/index.js +15 -1
  24. package/src/core/agent/skills/inspector.js +317 -0
  25. package/src/core/agent/skills/loader.js +22 -18
  26. package/src/core/agent/stream/turn-accumulator.js +73 -0
  27. package/src/core/agent/suggestions.js +37 -0
  28. package/src/core/agent/super-agent.js +7 -1
  29. package/src/core/agent/tools/handlers/_git.js +50 -0
  30. package/src/core/agent/tools/handlers/add-project.js +5 -2
  31. package/src/core/agent/tools/handlers/call-runtime.js +3 -2
  32. package/src/core/agent/tools/handlers/git-diff.js +44 -0
  33. package/src/core/agent/tools/handlers/git-log.js +38 -0
  34. package/src/core/agent/tools/handlers/git-show.js +34 -0
  35. package/src/core/agent/tools/handlers/git-status.js +61 -0
  36. package/src/core/agent/tools/handlers/transcribe-audio.js +1 -1
  37. package/src/core/agent/tools/helpers.js +2 -2
  38. package/src/core/agent/tools/names.js +169 -0
  39. package/src/core/agent/tools/registry-bridge.js +6 -14
  40. package/src/core/agent/tools/registry.js +103 -69
  41. package/src/core/apc/context-copy.js +27 -0
  42. package/src/core/apc/notes.js +19 -0
  43. package/src/core/apc/parser.js +12 -5
  44. package/src/core/apc/paths.js +87 -0
  45. package/src/core/apc/scaffold.js +82 -76
  46. package/src/core/apc/skill-sync.js +10 -0
  47. package/src/{host/daemon/plugins → core/channels}/telegram/dispatch.js +38 -16
  48. package/src/core/config/index.js +24 -2
  49. package/src/core/config/redact.js +95 -0
  50. package/src/core/constants/channels.js +2 -0
  51. package/src/core/constants/code-modes.js +10 -0
  52. package/src/core/constants/index.js +1 -0
  53. package/src/core/deck/manifest.js +186 -0
  54. package/src/core/engines/catalog.js +83 -0
  55. package/src/core/{tools → http-tools}/browser.js +0 -1
  56. package/src/core/{tools → http-tools}/fetch.js +0 -1
  57. package/src/core/{tools → http-tools}/glob.js +0 -1
  58. package/src/core/{tools → http-tools}/grep.js +0 -1
  59. package/src/core/{tools → http-tools}/registry.js +0 -1
  60. package/src/core/{tools → http-tools}/search.js +0 -1
  61. package/src/core/i18n/en.js +9 -0
  62. package/src/core/i18n/es.js +12 -0
  63. package/src/core/i18n/index.js +54 -0
  64. package/src/core/i18n/pt.js +9 -0
  65. package/src/core/identity/telegram.js +2 -1
  66. package/src/core/mcp/runner.js +272 -14
  67. package/src/core/mcp/sources.js +3 -2
  68. package/src/core/routines/index.js +16 -0
  69. package/src/{host/daemon/routines.js → core/routines/runner.js} +36 -103
  70. package/src/core/runtime-skills/apc-context/SKILL.md +159 -0
  71. package/src/core/runtime-skills/apx/SKILL.md +83 -0
  72. package/src/core/runtime-skills/apx-agency-agents/SKILL.md +125 -0
  73. package/src/core/runtime-skills/apx-agent/SKILL.md +97 -0
  74. package/src/core/runtime-skills/apx-mcp/SKILL.md +111 -0
  75. package/src/core/runtime-skills/apx-mcp-builder/SKILL.md +169 -0
  76. package/{skills → src/core/runtime-skills}/apx-project/SKILL.md +20 -29
  77. package/src/core/runtime-skills/apx-routine/SKILL.md +127 -0
  78. package/src/core/runtime-skills/apx-runtime/SKILL.md +99 -0
  79. package/src/core/runtime-skills/apx-sessions/SKILL.md +232 -0
  80. package/src/core/runtime-skills/apx-skill-builder/SKILL.md +129 -0
  81. package/{skills → src/core/runtime-skills}/apx-task/SKILL.md +18 -21
  82. package/src/core/runtime-skills/apx-telegram/SKILL.md +120 -0
  83. package/src/core/runtime-skills/apx-voice/SKILL.md +117 -0
  84. package/src/core/runtime-skills/{claude-code.md → claude-code/SKILL.md} +1 -0
  85. package/src/core/runtime-skills/{codex-cli.md → codex-cli/SKILL.md} +1 -0
  86. package/src/core/runtime-skills/{opencode-cli.md → opencode-cli/SKILL.md} +1 -0
  87. package/src/core/runtime-skills/{openrouter.md → openrouter/SKILL.md} +1 -0
  88. package/src/{host/daemon/env-detect.js → core/runtimes/detect.js} +1 -1
  89. package/src/core/stores/code-sessions.js +50 -2
  90. package/src/core/stores/routine-memory.js +1 -1
  91. package/src/core/stores/sessions-search.js +121 -0
  92. package/src/core/stores/sessions.js +38 -0
  93. package/src/core/vars/index.js +14 -0
  94. package/src/core/vars/interpolate.js +86 -0
  95. package/src/core/vars/sources.js +151 -0
  96. package/src/core/voice/audio-decode.js +38 -0
  97. package/src/core/voice/transcription.js +225 -0
  98. package/src/host/daemon/api/admin-config.js +5 -82
  99. package/src/host/daemon/api/agents.js +5 -5
  100. package/src/host/daemon/api/code.js +17 -169
  101. package/src/host/daemon/api/config.js +3 -4
  102. package/src/host/daemon/api/conversations.js +8 -29
  103. package/src/host/daemon/api/deck.js +37 -404
  104. package/src/host/daemon/api/engines.js +1 -80
  105. package/src/host/daemon/api/exec.js +1 -1
  106. package/src/host/daemon/api/mcps.js +32 -0
  107. package/src/host/daemon/api/routines.js +1 -1
  108. package/src/host/daemon/api/runtimes.js +4 -3
  109. package/src/host/daemon/api/sessions-search.js +24 -140
  110. package/src/host/daemon/api/sessions.js +12 -30
  111. package/src/host/daemon/api/shared.js +2 -1
  112. package/src/host/daemon/api/skills.js +140 -6
  113. package/src/host/daemon/api/super-agent.js +56 -1
  114. package/src/host/daemon/api/telegram.js +1 -11
  115. package/src/host/daemon/api/tools.js +6 -6
  116. package/src/host/daemon/api/transcribe.js +2 -2
  117. package/src/host/daemon/api/vars.js +137 -0
  118. package/src/host/daemon/api/voice.js +13 -290
  119. package/src/host/daemon/api.js +2 -0
  120. package/src/host/daemon/db.js +6 -6
  121. package/src/host/daemon/deck-exec.js +148 -0
  122. package/src/host/daemon/index.js +20 -3
  123. package/src/host/daemon/plugins/telegram/index.js +9 -9
  124. package/src/host/daemon/routines-scheduler.js +64 -0
  125. package/src/host/daemon/smoke.js +3 -2
  126. package/src/host/daemon/whisper-server.js +225 -0
  127. package/src/interfaces/cli/branding.js +53 -0
  128. package/src/interfaces/cli/commands/agent.js +3 -2
  129. package/src/interfaces/cli/commands/command.js +2 -3
  130. package/src/interfaces/cli/commands/messages.js +6 -2
  131. package/src/interfaces/cli/commands/pair.js +5 -4
  132. package/src/interfaces/cli/commands/search.js +1 -1
  133. package/src/interfaces/cli/commands/sessions.js +3 -2
  134. package/src/interfaces/cli/commands/skills.js +290 -55
  135. package/src/interfaces/cli/index.js +84 -2
  136. package/src/interfaces/web/dist/assets/index-C0fm31dY.js +618 -0
  137. package/src/interfaces/web/dist/assets/index-C0fm31dY.js.map +1 -0
  138. package/src/interfaces/web/dist/assets/index-UcAqlBO6.css +1 -0
  139. package/src/interfaces/web/dist/index.html +2 -2
  140. package/src/interfaces/web/package-lock.json +182 -182
  141. package/src/interfaces/web/src/components/ModelCombobox.tsx +2 -1
  142. package/src/interfaces/web/src/components/TelegramChannelDialog.tsx +1 -1
  143. package/src/interfaces/web/src/components/chat/AskAnswersCard.tsx +76 -0
  144. package/src/interfaces/web/src/components/chat/MessageBubble.tsx +37 -4
  145. package/src/interfaces/web/src/components/chat/MessageList.tsx +23 -1
  146. package/src/interfaces/web/src/components/chat/ModelPicker.tsx +3 -1
  147. package/src/interfaces/web/src/components/code/CodeArtifactsTab.tsx +4 -4
  148. package/src/interfaces/web/src/components/code/CodeChangesTab.tsx +1 -1
  149. package/src/interfaces/web/src/components/code/CodeFileTree.tsx +3 -2
  150. package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +3 -2
  151. package/src/interfaces/web/src/components/code/CodeTerminal.tsx +3 -2
  152. package/src/interfaces/web/src/components/config/GlobalConfigEditor.tsx +2 -1
  153. package/src/interfaces/web/src/components/deck/WidgetRow.tsx +2 -1
  154. package/src/interfaces/web/src/components/inputs/KeyValueList.tsx +93 -0
  155. package/src/interfaces/web/src/components/inputs/VarTokenInput.tsx +449 -0
  156. package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +2 -1
  157. package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +2 -2
  158. package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +73 -4
  159. package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +222 -0
  160. package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +3 -2
  161. package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +3 -2
  162. package/src/interfaces/web/src/components/ui/chat-input.tsx +5 -4
  163. package/src/interfaces/web/src/components/ui/sidebar.tsx +3 -2
  164. package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +2 -1
  165. package/src/interfaces/web/src/constants/index.ts +1 -1
  166. package/src/interfaces/web/src/hooks/useChat.ts +19 -0
  167. package/src/interfaces/web/src/i18n/en.ts +175 -7
  168. package/src/interfaces/web/src/i18n/es.ts +180 -15
  169. package/src/interfaces/web/src/lib/api/mcps.ts +25 -0
  170. package/src/interfaces/web/src/lib/api/skills.ts +70 -0
  171. package/src/interfaces/web/src/lib/api/vars.ts +38 -0
  172. package/src/interfaces/web/src/lib/api.ts +1 -0
  173. package/src/interfaces/web/src/screens/ProjectScreen.tsx +8 -31
  174. package/src/interfaces/web/src/screens/SettingsScreen.tsx +6 -2
  175. package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +1 -1
  176. package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +4 -3
  177. package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +7 -6
  178. package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +4 -3
  179. package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +1 -1
  180. package/src/interfaces/web/src/screens/project/ConfigTab.tsx +132 -1
  181. package/src/interfaces/web/src/screens/project/McpsTab.tsx +549 -104
  182. package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +1 -1
  183. package/src/interfaces/web/src/screens/project/VarsTab.tsx +300 -0
  184. package/src/interfaces/web/src/types/daemon.ts +15 -0
  185. package/skills/apx-agency-agents/SKILL.md +0 -141
  186. package/skills/apx-agent/SKILL.md +0 -100
  187. package/skills/apx-mcp-builder/SKILL.md +0 -183
  188. package/skills/apx-routine/SKILL.md +0 -140
  189. package/skills/apx-runtime/SKILL.md +0 -117
  190. package/skills/apx-sessions/SKILL.md +0 -281
  191. package/skills/apx-skill-builder/SKILL.md +0 -153
  192. package/skills/apx-telegram/SKILL.md +0 -131
  193. package/skills/apx-voice/SKILL.md +0 -137
  194. package/src/core/agent/prompts/action-discipline.md +0 -24
  195. package/src/core/agent/prompts/super-agent-base.md +0 -42
  196. package/src/host/daemon/transcription.js +0 -538
  197. package/src/host/daemon/whisper-transcribe.py +0 -73
  198. package/src/interfaces/web/dist/assets/index-Aaiw8BZN.css +0 -1
  199. package/src/interfaces/web/dist/assets/index-DPqtjDjh.js +0 -602
  200. package/src/interfaces/web/dist/assets/index-DPqtjDjh.js.map +0 -1
  201. /package/src/{host/daemon → core/apc}/projects-helpers.js +0 -0
  202. /package/src/{host/daemon/plugins → core/channels}/telegram/ask.js +0 -0
  203. /package/src/{host/daemon/plugins → core/channels}/telegram/helpers.js +0 -0
  204. /package/src/{host/daemon/plugins → core/channels}/telegram/media.js +0 -0
  205. /package/src/core/{tools → http-tools}/index.js +0 -0
  206. /package/src/{host/daemon/compact.js → core/stores/conversations-compactor.js} +0 -0
  207. /package/src/{host/daemon → core/stores}/conversations.js +0 -0
  208. /package/src/{host/daemon → core/util}/thinking.js +0 -0
@@ -1,77 +1,85 @@
1
- // Prompt builder for the APX default agent known internally as the
2
- // "super-agent". That name is a MODE descriptor (the daemon-level tool-using
3
- // loop that runs when no project agent is named), not a persona the user
4
- // should ever see. The model is told its real display name comes from
5
- // ~/.apx/identity.json; "super-agent" only appears in code, file paths, CLI
6
- // flags, and channel meta.
1
+ // Unified prompt builder for ANY agent (super-agent OR project agent).
2
+ //
3
+ // The system prompt is assembled from layered fragments:
4
+ //
5
+ // 1. core/agent-base.md common: tool usage, memory, hard rules applies to every agent
6
+ // 2. core/super-agent.md OR core/project-agent.md — the role delta
7
+ // 3. # Agent profile identity (name, personality, owner, language)
8
+ // 4. # Project / context project pin, registered projects index, AGENTS.md
9
+ // 5. # Memory self-memory or relevant memory block, active threads
10
+ // 6. # Channel channel-specific formatting rules
11
+ // 7. # Discipline action.md + (two-segment OR single-segment) + voice mode
12
+ // 8. # Suffix channel-specific format directives (suggestions JSON, etc.)
13
+ //
14
+ // Sections are dropped when empty (no project context for super-agent on a
15
+ // generic CLI call, no self-memory for project agents, etc.).
7
16
  import fs from "node:fs";
8
17
  import path from "node:path";
9
18
  import { fileURLToPath } from "node:url";
10
19
  import { readIdentity } from "../identity/index.js";
20
+ import { agentsMdFile } from "../apc/paths.js";
11
21
  import { readSelfMemoryForPrompt } from "./self-memory.js";
12
22
  import { buildSkillsHintBlock } from "./skills/catalog.js";
23
+ import { CHANNELS } from "#core/constants/channels.js";
13
24
 
14
25
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
26
  const PROMPTS_DIR = path.join(__dirname, "prompts");
16
- const BASE_PROMPT_PATH = path.join(PROMPTS_DIR, "super-agent-base.md");
17
27
 
18
- // Action discipline + chit-chat rulessame file used by project agents
19
- // (buildAgentSystem in agent-system.js), loaded once here for the super-agent.
20
- const ACTION_DISCIPLINE = fs
21
- .readFileSync(path.join(PROMPTS_DIR, "action-discipline.md"), "utf8")
22
- .trimEnd();
23
-
24
- const promptCache = new Map();
25
-
26
- /** @deprecated use super-agent-base.md */
27
- const LEGACY_PROMPT_PATH = path.join(PROMPTS_DIR, "super-agent-default.md");
28
-
29
- // Channels are SURFACES (where the user is). Voice is NOT a channel — it's a
30
- // MODE that layers on top of a surface (see buildVoiceModeBlock); a spoken deck
31
- // turn is channel "deck" + voice mode, not its own channel.
28
+ // Channels are SURFACES. Voice is NOT a channel it's a MODE that layers on
29
+ // top of a surface (see buildVoiceModeBlock); a spoken deck turn is channel
30
+ // "deck" + voice mode, not its own channel.
32
31
  const CHANNEL_PROMPT_FILES = {
33
- telegram: "channels/telegram.md",
34
- cli: "channels/cli.md",
35
- routine: "channels/routine.md",
36
- api: "channels/api.md",
37
- web: "channels/web.md", // web big chat (long-form, full tools)
38
- web_sidebar: "channels/web_sidebar.md", // web quick chat (short, lightweight)
39
- web_code: "channels/web_code.md", // web Code module (rich coding session)
40
- deck: "channels/deck.md", // cockpit dashboard
41
- desktop: "channels/desktop.md", // PC floating module (was "overlay")
42
- code: "channels/code.md", // `apx code` — terminal coding session
32
+ [CHANNELS.TELEGRAM]: "channels/telegram.md",
33
+ [CHANNELS.CLI]: "channels/cli.md",
34
+ [CHANNELS.ROUTINE]: "channels/routine.md",
35
+ [CHANNELS.API]: "channels/api.md",
36
+ [CHANNELS.WEB]: "channels/web.md",
37
+ [CHANNELS.WEB_SIDEBAR]: "channels/web_sidebar.md",
38
+ [CHANNELS.WEB_CODE]: "channels/web_code.md",
39
+ [CHANNELS.DECK]: "channels/deck.md",
40
+ [CHANNELS.DESKTOP]: "channels/desktop.md",
41
+ [CHANNELS.CODE]: "channels/code.md",
43
42
  };
44
43
 
45
- // Voice mode: spoken-reply rules layered on any surface when the turn will be
46
- // read aloud by TTS (deck voice overlay, desktop module, etc). Injected with
47
- // high recency (right before systemSuffix) so weaker models don't bury it.
44
+ // Channels where the user CAN see two text segments per turn (chat history is
45
+ // visible). Voice / single-surface channels get single-segment discipline.
46
+ const TWO_SEGMENT_CHANNELS = new Set([
47
+ CHANNELS.TELEGRAM,
48
+ CHANNELS.WEB,
49
+ CHANNELS.WEB_SIDEBAR,
50
+ CHANNELS.WEB_CODE,
51
+ CHANNELS.CODE,
52
+ CHANNELS.API,
53
+ CHANNELS.CLI,
54
+ ]);
55
+
48
56
  const VOICE_MODE_FILE = "modes/voice.md";
49
57
 
50
- export function buildVoiceModeBlock(active) {
51
- if (!active) return "";
52
- try {
53
- return loadPrompt(VOICE_MODE_FILE);
54
- } catch {
55
- return "";
56
- }
57
- }
58
+ // ---------------------------------------------------------------------------
59
+ // Prompt loading
60
+ // ---------------------------------------------------------------------------
61
+
62
+ const promptCache = new Map();
58
63
 
59
64
  export function loadPrompt(relativePath) {
60
65
  const key = relativePath.replace(/\\/g, "/");
61
66
  if (promptCache.has(key)) return promptCache.get(key);
62
- const full = path.join(PROMPTS_DIR, key);
63
- const text = fs.readFileSync(full, "utf8");
67
+ const text = fs.readFileSync(path.join(PROMPTS_DIR, key), "utf8").trimEnd();
64
68
  promptCache.set(key, text);
65
69
  return text;
66
70
  }
67
71
 
72
+ const AGENT_BASE = loadPrompt("core/agent-base.md");
73
+ const SUPER_AGENT_ROLE = loadPrompt("core/super-agent.md");
74
+ const PROJECT_AGENT_ROLE = loadPrompt("core/project-agent.md");
75
+ const ACTION_DISCIPLINE = loadPrompt("discipline/action.md");
76
+ const TWO_SEGMENT = loadPrompt("discipline/two-segment.md");
77
+ const SINGLE_SEGMENT = loadPrompt("discipline/single-segment.md");
78
+
79
+ // Back-compat shim — a few callers/tests still want the raw default prompt.
68
80
  export function loadDefaultSystemPrompt() {
69
- if (fs.existsSync(BASE_PROMPT_PATH)) return loadPrompt("super-agent-base.md");
70
- if (fs.existsSync(LEGACY_PROMPT_PATH)) return loadPrompt("super-agent-default.md");
71
- throw new Error("super-agent base prompt not found");
81
+ return [AGENT_BASE, SUPER_AGENT_ROLE].join("\n\n");
72
82
  }
73
-
74
- /** @deprecated use loadDefaultSystemPrompt — kept for tests/imports */
75
83
  export const DEFAULT_SYSTEM = loadDefaultSystemPrompt();
76
84
 
77
85
  export function renderPromptTemplate(template, vars = {}) {
@@ -81,23 +89,44 @@ export function renderPromptTemplate(template, vars = {}) {
81
89
  });
82
90
  }
83
91
 
92
+ // ---------------------------------------------------------------------------
93
+ // Channel + mode blocks
94
+ // ---------------------------------------------------------------------------
95
+
84
96
  export function buildChannelContextBlock(channel, meta = {}) {
85
97
  const rel = CHANNEL_PROMPT_FILES[String(channel || "").toLowerCase()];
86
98
  if (!rel) return "";
87
99
  return renderPromptTemplate(loadPrompt(rel), meta);
88
100
  }
89
101
 
90
- // Project startup rules. When APX runs its OWN loop inside a project, load that
91
- // project's AGENTS.md into the prompt — the same convention Claude/Codex follow
92
- // with CLAUDE.md/AGENTS.md. `projectPath` flows in via channelMeta.projectPath
93
- // (set by the super-agent API, the code module, and routines). This is wired
94
- // ONLY into the super-agent prompt: when APX delegates to an external engine,
95
- // that engine reads AGENTS.md itself. Size-capped to protect the prompt budget.
102
+ export function buildVoiceModeBlock(active) {
103
+ if (!active) return "";
104
+ try {
105
+ return loadPrompt(VOICE_MODE_FILE);
106
+ } catch {
107
+ return "";
108
+ }
109
+ }
110
+
111
+ // Pick the right segmenting discipline for the channel (and whether voice
112
+ // mode overrides it).
113
+ function buildSegmentDiscipline({ channel, voice }) {
114
+ if (voice) return SINGLE_SEGMENT;
115
+ if (TWO_SEGMENT_CHANNELS.has(String(channel || "").toLowerCase())) return TWO_SEGMENT;
116
+ // routine / deck / desktop / unknown → single-segment (single visible reply)
117
+ return SINGLE_SEGMENT;
118
+ }
119
+
120
+ // ---------------------------------------------------------------------------
121
+ // Project guidance — AGENTS.md of the pinned project, size-capped.
122
+ // ---------------------------------------------------------------------------
123
+
96
124
  export const PROJECT_AGENTS_MAX_CHARS = 6000;
125
+
97
126
  export function buildProjectAgentsBlock(projectPath) {
98
127
  if (!projectPath) return "";
99
128
  try {
100
- const file = path.join(projectPath, "AGENTS.md");
129
+ const file = agentsMdFile(projectPath);
101
130
  if (!fs.existsSync(file)) return "";
102
131
  let text = fs.readFileSync(file, "utf8").trim();
103
132
  if (!text) return "";
@@ -110,13 +139,17 @@ export function buildProjectAgentsBlock(projectPath) {
110
139
  }
111
140
  }
112
141
 
113
- export function buildUserContextBlock(identity, globalConfig = {}) {
142
+ // ---------------------------------------------------------------------------
143
+ // Identity / user / relationship blocks (shared across agents)
144
+ // ---------------------------------------------------------------------------
145
+
146
+ export function buildUserContextBlock(identity, globalConfig = {}, { agentName } = {}) {
114
147
  const user = globalConfig?.user || {};
115
148
  const lang = user.language || identity?.language || "en";
116
- const lines = ["# User & identity"];
149
+ const lines = ["# Agent profile"];
117
150
 
118
- const agentName = identity?.agent_name || globalConfig?.super_agent?.name;
119
- if (agentName) lines.push(`Your name is ${agentName}.`);
151
+ const name = agentName || identity?.agent_name || globalConfig?.super_agent?.name;
152
+ if (name) lines.push(`Your name is ${name}.`);
120
153
  if (identity?.personality) lines.push(`Your personality: ${identity.personality}.`);
121
154
  if (identity?.owner_name) lines.push(`Your owner is ${identity.owner_name}.`);
122
155
  if (identity?.owner_context) lines.push(`Owner context: ${identity.owner_context}`);
@@ -124,9 +157,7 @@ export function buildUserContextBlock(identity, globalConfig = {}) {
124
157
  lines.push(
125
158
  `Reply in the language with ISO 639-1 code "${lang}" unless the user explicitly switches language for that turn.`
126
159
  );
127
- if (user.locale) {
128
- lines.push(`Preferred locale or dialect: ${user.locale}.`);
129
- }
160
+ if (user.locale) lines.push(`Preferred locale or dialect: ${user.locale}.`);
130
161
  if (user.timezone) {
131
162
  lines.push(
132
163
  `User timezone: ${user.timezone}. Use it for local time and schedules unless the user specifies otherwise.`
@@ -136,15 +167,13 @@ export function buildUserContextBlock(identity, globalConfig = {}) {
136
167
  return lines.join("\n");
137
168
  }
138
169
 
139
- /** Back-compat wrapper — second arg is ISO language only (no full config). */
170
+ /** Back-compat wrapper — second arg is ISO language only. */
140
171
  export function buildIdentityBlock(identity, userLang = "en") {
141
172
  return buildUserContextBlock(identity, { user: { language: userLang } });
142
173
  }
143
174
 
144
- // "Who you're talking to" block. Agent-agnostic: built once from the resolved
145
- // sender (see core/identity/telegram.js) and injected into BOTH the super-agent
146
- // prompt and any routed project-agent prompt, so identification doesn't depend
147
- // on which agent answers. Returns "" when there's no sender info.
175
+ // "Who you're talking to" block — agent-agnostic, built once from the resolved
176
+ // sender (see core/identity/telegram.js). Returns "" when there's no sender.
148
177
  export function buildRelationshipBlock(sender) {
149
178
  if (!sender || sender.userId == null) return "";
150
179
  const handle = sender.username ? ` (@${sender.username})` : "";
@@ -154,41 +183,30 @@ export function buildRelationshipBlock(sender) {
154
183
  lines.push(
155
184
  "This is a Telegram GROUP chat with multiple people — do NOT assume a single owner."
156
185
  );
157
- lines.push(
158
- `Sender of this message: ${sender.name}${handle}, role: ${sender.role}.`
159
- );
186
+ lines.push(`Sender of this message: ${sender.name}${handle}, role: ${sender.role}.`);
160
187
  } else if (sender.isOwner) {
161
188
  lines.push(
162
- `You are talking to your owner, ${sender.name}. Treat them as the owner — ` +
163
- "never ask their name or who they are; you already know them."
189
+ `You are talking to your owner, ${sender.name}. Treat them as the owner — never ask their name or who they are.`
164
190
  );
165
191
  } else if (sender.role && sender.role !== "guest") {
166
192
  lines.push(`You are talking to ${sender.name}${handle}, role: ${sender.role}.`);
167
193
  } else {
168
194
  lines.push(
169
- `You are talking to ${sender.name}${handle}, who is NOT a recognized contact ` +
170
- "(role: guest, no permissions)."
171
- );
172
- lines.push(
173
- "Politely say you don't know them yet and ask who they are; tell them you'll " +
174
- "note it down, but that you cannot grant any role or permissions yourself — " +
175
- "only the owner or someone via terminal/web can assign a role. Do not perform " +
176
- "privileged or destructive actions on their behalf."
195
+ `You are talking to ${sender.name}${handle} (role: guest, no permissions). Politely ask who they are you'll note it down but cannot grant any role yourself.`
177
196
  );
178
197
  }
179
198
  if (sender.note) lines.push(`Notes on this contact: ${sender.note}`);
180
199
  return lines.join("\n");
181
200
  }
182
201
 
183
- // The super-agent's own notebook (~/.apx/memory.md), bounded for the prompt.
184
- // Returns "" when empty so the block is dropped entirely.
202
+ // Super-agent notebook (~/.apx/memory.md), bounded. Returns "" when empty.
203
+ // Project agents have their own per-agent memory.md handled in buildAgentSystem.
185
204
  export function buildSelfMemoryBlock() {
186
205
  const slice = readSelfMemoryForPrompt();
187
206
  if (!slice) return "";
188
207
  return [
189
- "# Your notebook (self-memory)",
190
- "Durable things you chose to remember across sessions. Treat as known facts;",
191
- "update with the `remember` tool. Call read_self_memory if this looks truncated.",
208
+ "# Notebook",
209
+ "Durable facts you chose to remember. Update with the `remember` tool. Read full with `read_self_memory` if truncated.",
192
210
  "",
193
211
  slice,
194
212
  ].join("\n");
@@ -200,6 +218,26 @@ export function isSuperAgentEnabled(cfg) {
200
218
  return sa.enabled !== false;
201
219
  }
202
220
 
221
+ // ---------------------------------------------------------------------------
222
+ // Project index — renders the registered-project list cleanly when relevant.
223
+ // Omits the [kind] prefix when kind="default" so we don't get `[default] "default"`.
224
+ // ---------------------------------------------------------------------------
225
+
226
+ function buildProjectIndex(projects) {
227
+ const list = projects?.list?.() || [];
228
+ if (!list.length) return "";
229
+ const lines = list.map((p) => {
230
+ if (p.id === 0) return ` ${p.id}: "${p.name}" (global workspace, ${p.path})`;
231
+ const kindTag = p.kind && p.kind !== "default" && p.kind !== "other" ? ` [${p.kind}]` : "";
232
+ return ` ${p.id}:${kindTag} "${p.name}" (${p.path})`;
233
+ });
234
+ return ["# Registered projects (index only — call tools for details)", ...lines].join("\n");
235
+ }
236
+
237
+ // ---------------------------------------------------------------------------
238
+ // Super-agent system prompt
239
+ // ---------------------------------------------------------------------------
240
+
203
241
  export function buildSuperAgentSystem({
204
242
  globalConfig,
205
243
  projects,
@@ -207,67 +245,83 @@ export function buildSuperAgentSystem({
207
245
  contextNote = "",
208
246
  channel = "",
209
247
  channelMeta = {},
210
- // Pre-rendered "who you're talking to" block (see buildRelationshipBlock).
211
- // Injected right after the user/identity block so the model knows the
212
- // sender's identity and role before anything else.
248
+ // Pre-rendered "who you're talking to" block.
213
249
  relationshipBlock = "",
214
- // Channel-specific addendum the super-agent caller can inject
215
- // e.g. voice.js asks for a trailing ```suggestions``` JSON block on
216
- // voice/deck surfaces. Kept separate from contextNote so it lives
217
- // at the end of the system prompt (where format directives belong),
218
- // not mixed in with situational context.
250
+ // Channel-specific format directive appended at the very end (e.g.
251
+ // ```suggestions``` block for voice/deck).
219
252
  systemSuffix = "",
220
- // Pre-rendered output of the Memory Broker (Pieza 4): a [RELEVANT MEMORY]
221
- // block built from the RAG retriever + recent memory.md entries. When
222
- // provided it REPLACES the always-on self-memory slice (it already includes
223
- // the latest notebook entries). "" falls back to the plain notebook slice.
253
+ // Pre-rendered Memory Broker output ([RELEVANT MEMORY] block). When set, it
254
+ // REPLACES the plain self-memory slice (it already includes the latest entries).
224
255
  memoryBlock = "",
225
- // Pre-rendered "# Active threads on other channels" block (recency-based
226
- // cross-channel awareness; see core/memory/active-threads.js). "" → omitted.
256
+ // Pre-rendered "# Active threads on other channels" block.
227
257
  activeThreadsBlock = "",
228
- // Compact "# Tools adicionales (activación on-demand)" block: instructions +
229
- // the NAMES (no schemas) of tools that exist but aren't loaded on this
230
- // channel, so the model knows they're reachable via discover_tools without
231
- // paying for their schemas. "" → omitted (full channels load everything).
258
+ // Compact "tools you can activate" hint (names of not-loaded tools).
232
259
  lazyToolsBlock = "",
260
+ // When the skill inspector middleware is active, the daemon already injected
261
+ // the right skill bodies/hints into contextNote — and the catalog-wide slug
262
+ // dump becomes counterproductive (it nudges the model to load skills the
263
+ // inspector explicitly decided not to surface). Setting this to true removes
264
+ // buildSkillsHintBlock from the prompt.
265
+ skipSkillsHint = false,
233
266
  }) {
234
- const sa = globalConfig.super_agent;
235
- const projectIndex = projects
236
- .list()
237
- .map((p) => ` ${p.id}: ${p.id === 0 ? "[default]" : "[project]"} "${p.name}" (${p.path})`)
238
- .join("\n");
239
-
267
+ const sa = globalConfig.super_agent || {};
240
268
  const identity = (() => {
241
- try {
242
- return readIdentity();
243
- } catch {
244
- return null;
245
- }
269
+ try { return readIdentity(); } catch { return null; }
246
270
  })();
247
271
 
272
+ const channelLow = String(channel || "").toLowerCase();
273
+ const voice = !!channelMeta?.voice || channelLow === "voice";
274
+
275
+ // The super-agent's identity from config overrides the file-based delta when
276
+ // sa.system is set explicitly (user tweaked the system prompt). Otherwise
277
+ // we layer agent-base + super-agent role.
278
+ const roleBlock = sa.system || [AGENT_BASE, SUPER_AGENT_ROLE].join("\n\n");
279
+
280
+ // Additive personalization layered ON TOP of the role (unlike sa.system,
281
+ // which fully replaces it). Lets the owner give the super-agent durable
282
+ // custom instructions without rewriting the whole base prompt.
283
+ const customInstructions =
284
+ sa.instructions && String(sa.instructions).trim()
285
+ ? `# Custom instructions\n${String(sa.instructions).trim()}`
286
+ : "";
287
+
248
288
  const channelBlock = buildChannelContextBlock(channel, channelMeta);
249
289
  const extraContext = [channelBlock, contextNote].filter(Boolean).join("\n\n");
250
- // Voice is a mode, not a channel: the caller flags a spoken turn via
251
- // channelMeta.voice (or the legacy channel === "voice"). The block goes last,
252
- // next to systemSuffix, so format directives keep recency.
253
- const voiceModeBlock = buildVoiceModeBlock(channelMeta?.voice || channel === "voice");
290
+ const voiceBlock = buildVoiceModeBlock(voice);
291
+ const segmentDiscipline = buildSegmentDiscipline({ channel: channelLow, voice });
254
292
 
255
293
  return [
256
- sa.system || loadDefaultSystemPrompt(),
294
+ roleBlock,
257
295
  buildUserContextBlock(identity, globalConfig),
296
+ customInstructions,
258
297
  memoryBlock || buildSelfMemoryBlock(),
259
298
  activeThreadsBlock,
260
299
  relationshipBlock,
261
300
  extraContext,
262
- "# Registered projects (just the index — call tools for details)",
263
- projectIndex || "(no projects registered)",
301
+ buildProjectIndex(projects),
264
302
  buildProjectAgentsBlock(channelMeta?.projectPath),
265
- buildSkillsHintBlock(listSkills),
303
+ skipSkillsHint ? "" : buildSkillsHintBlock(listSkills),
266
304
  lazyToolsBlock,
267
- voiceModeBlock,
305
+ voiceBlock,
268
306
  ACTION_DISCIPLINE,
307
+ segmentDiscipline,
269
308
  systemSuffix,
270
309
  ]
271
310
  .filter(Boolean)
272
311
  .join("\n\n");
273
312
  }
313
+
314
+ // ---------------------------------------------------------------------------
315
+ // Shared exports re-used by build-agent-system.js
316
+ // ---------------------------------------------------------------------------
317
+
318
+ export const PROMPTS = {
319
+ AGENT_BASE,
320
+ SUPER_AGENT_ROLE,
321
+ PROJECT_AGENT_ROLE,
322
+ ACTION_DISCIPLINE,
323
+ TWO_SEGMENT,
324
+ SINGLE_SEGMENT,
325
+ };
326
+
327
+ export { buildSegmentDiscipline };
@@ -1,16 +1,18 @@
1
1
  # Channel context
2
- Channel: **code** (`apx code`, the interactive APX coding session in the terminal) the same OpenCode-style coding surface as the web Code module, just rendered in the terminal. You can read, search, edit files and run shell commands.
2
+ **Code** `apx code`, the interactive APX coding session in the terminal. The same OpenCode-style coding surface as the web Code module.
3
3
 
4
- - CWD: {{cwd}}
5
- - References to "this directory", "this project", "here", "current folder" mean the CWD above use it as the path argument; do not ask for a path
4
+ CWD: {{cwd}}
5
+ "this directory" / "this project" / "here" / "current folder" = the CWD above; use it as the path argument, don't ask.
6
6
 
7
- Working style — KEEP GOING UNTIL THE TASK IS DONE (build mode):
8
- - You are an autonomous coding agent. Once the user gives a task, complete the WHOLE thing in this turn: chain as many tool calls as needed (read → edit → run → verify), do not stop after one or two steps.
9
- - NEVER stop to ask "do you want me to…?" / "should I continue?" / "is that OK?". You already have permission on this surface — just do it. Only ask if the task is truly ambiguous and you genuinely cannot proceed.
10
- - NEVER announce an action and then end your turn ("now I'll edit the file." → stop). If you say you will do something, immediately call the tool and actually do it in the same turn.
11
- - After each tool result, decide the next concrete step and take it. Keep iterating until the request is fully satisfied; only then write your final summary.
12
- - If something fails, read the error, fix it, and retry — don't hand the problem back to the user.
7
+ Working style — keep going until the task is done:
8
+ - Once the user gives a task, complete the WHOLE thing in this turn. Chain tool calls (read → edit → run → verify); don't stop after one step.
9
+ - Never stop to ask "should I continue?". You have permission on this surface — just do it.
10
+ - If you say you will do something, immediately call the tool and do it in the same turn.
11
+ - After each tool result, decide the next concrete step and take it. Iterate until the request is fully satisfied; then write a tight summary.
12
+ - If something fails, read the error, fix it, retry. Don't hand the problem back.
13
+ - Use git tools (git_status, git_diff, git_log) to verify and report changes — don't blind-edit.
13
14
 
14
15
  Formatting:
15
- - Markdown OK; keep readable; use code diffs when editing.
16
+ - Markdown OK. Code fences for snippets and diffs.
16
17
  - Lead with the result; keep prose tight. Don't re-paste full tool output the user can already see.
18
+ - Prefer surgical `edit_file` over rewrites.
@@ -1,36 +1,9 @@
1
1
  # Channel context
2
- Channel: **desktop** (the floating APX module open on the user's PC). A small
3
- always-on-top Electron capsule the user invokes with a global hotkey
4
- (default ⌘G / Ctrl+G), then either holds-to-speak or types a quick line.
5
- Companion to the deck — fast, action-first, conversational. Not a long-form
6
- workspace; the web admin (`/m/desktop`) handles config and the web big chat
7
- (`channel: web`) handles long sessions.
2
+ **Desktop** a small always-on-top Electron capsule the user invokes with a global hotkey (⌘G / Ctrl+G). Fast, action-first, conversational. The user holds-to-speak or types a quick line.
8
3
 
9
- Voice mode is ALWAYS active on this channel (the desktop plugin sets
10
- `channelMeta: { voice: true }`). Anything you write here will be spoken aloud
11
- by TTS, so default to spoken-friendly phrasing even when the user typed
12
- their input.
4
+ Voice mode is ALWAYS active on this channel your reply will be spoken aloud by TTS.
13
5
 
14
6
  Formatting:
15
- - 1–2 short sentences whenever possible. The user usually wants the action
16
- done and a tiny confirmation, not an explanation.
17
- - No markdown tables, no code fences, no bulleted lists unless the user
18
- explicitly asks. Plain prose only — these get read aloud verbatim.
19
- - No URLs / file paths spelled out — refer to them by name (e.g. "open
20
- Voices in the web admin" rather than "http://localhost:7430/m/voice").
21
- Use the user's language when phrasing it.
22
- - If a Voice mode block is present below, its rules win over anything here.
23
- - Bias hard toward DOING the action and reporting the result in one breath,
24
- rather than asking back. Confirm-after, not confirm-before, for
25
- reversible things.
26
-
27
- Don't repeat yourself (this matters — your messages are shown AND spoken):
28
- - Greet AT MOST once per conversation. If you already said hi, never greet
29
- again — jump straight to the answer.
30
- - When you call a tool, any line BEFORE it must be a 2–4 word filler only
31
- (e.g. "one moment…", "checking that…", in the user's language). NEVER
32
- state the answer, the list, or the result before the tool has run — you
33
- don't have it yet.
34
- - After the tool returns, give the result ONCE. Do not re-announce it, do not
35
- re-greet, do not restate the filler. One clean reply.
36
- - Never say the same thing twice across a single turn.
7
+ - Plain prose, 1–2 sentences. No markdown, no bullets, no code fences, no URLs (they get read aloud).
8
+ - Refer to paths by name ("the apx project", "the voices module"), not raw paths.
9
+ - Bias hard toward DOING reversible actions and reporting the result in one breath, rather than confirming first.
@@ -1,18 +1,7 @@
1
1
  # Channel context
2
- Channel: **telegram** (bot channel `{{channelName}}`, author: {{author}}, chat_id: {{chatId}}).
2
+ **Telegram** bot `{{channelName}}` · author: {{author}} · chat_id: {{chatId}}
3
3
  {{projectBlock}}{{routeBlock}}
4
4
  Formatting:
5
- - Plain text only no markdown tables; code fences only when quoting code
6
- - Keep replies brief (~6 sentences unless user asks for more)
7
- - Previous turns are conversational context only; re-call tools for facts
8
-
9
- What the user sees here: only your text segments. They do NOT see your tool calls, args, or intermediate results — those never reach Telegram.
10
-
11
- Two-segment turn (intro + answer):
12
- - When you call a tool, write a SHORT natural intro BEFORE the tool runs (2–8 words in the user's language: "Dale, voy a anotar eso", "Reviso eso", "Un momento, busco esos datos"). That lands as a Telegram message of its own so the user sees you're working.
13
- - AFTER the tool returns, write the substantive answer with the actual result or confirmation. That is the second Telegram message.
14
- - The intro NEVER contains the substantive content — at that point the tool hasn't run yet, so you don't know the result. Wrong: "¡Anotado! Sos Tech Lead en Bytetravel" BEFORE remember runs. Right: "Dale, voy a anotar eso" before, then "Listo, anoté que sos Tech Lead." after.
15
- - The answer NEVER restates the intro. They're complementary: filler + result, not the same content twice.
16
- - Greet at most ONCE per turn. If the intro opened with "Hola", the answer starts with the result, no second greeting.
17
-
18
- Turns without tools (small talk, "hola", "gracias"): a single message — the reply itself, no intro filler.
5
+ - Plain text only. No markdown tables; code fences only when quoting code.
6
+ - Brief — keep replies under ~6 sentences unless the user asks for more.
7
+ - The user sees only your text segments never your tool calls, args, or intermediate results.
@@ -1,20 +1,20 @@
1
1
  # Channel context
2
- Channel: **web_code** (the Code module in the web admin panel at `/m/code`) — a rich, OpenCode-style coding session scoped to a single project. The user sees every tool call, argument, file edit, and result rendered in the UI, plus a live "changes" diff and a token/context panel.
2
+ **Web Code** the Code module in the web admin at `/m/code`. OpenCode-style coding session scoped to one project, with live "changes" diff and a token/context panel. The user sees every tool call, arg, file edit, and result in the UI.
3
3
 
4
4
  Working project: **{{projectName}}** (id {{projectId}})
5
5
  Path: `{{projectPath}}`
6
- All file and shell tools resolve relative to that project path — operate inside it unless told otherwise.
6
+ File and shell tools resolve relative to that project path unless told otherwise.
7
7
 
8
8
  {{modeGuidance}}
9
9
 
10
- Working style — KEEP GOING UNTIL THE TASK IS DONE:
11
- - You are an autonomous coding agent. Once the user gives a task, complete the WHOLE thing in this turn: chain as many tool calls as needed (read → edit → run → verify), do not stop after one or two steps.
12
- - NEVER stop to ask "do you want me to…?" / "should I continue?" / "is that OK?". You already have permission on this surface — just do it. Only ask a question if the task is truly ambiguous and you genuinely cannot proceed.
13
- - NEVER announce an action and then end your turn ("now I'll edit the file." → stop). If you say you will do something, immediately call the tool and actually do it in the same turn.
14
- - After each tool result, decide the next concrete step and take it. Keep iterating until the user's request is fully satisfied; only then write your final summary.
15
- - If something fails, read the error, fix it, and retry — don't hand the problem back to the user.
10
+ Working style — keep going until the task is done:
11
+ - Complete the whole task in this turn. Chain tool calls (read → edit → run → verify); don't stop after one step.
12
+ - Never stop to ask "should I continue?". You have permission on this surface — just do it.
13
+ - If you announce an action, immediately call the tool in the same turn.
14
+ - After each tool result, decide the next step and take it. Iterate until the request is fully satisfied; then summarize.
15
+ - If something fails, read the error, fix it, retry.
16
+ - Use git tools (git_status, git_diff, git_log) to verify what changed before summarizing.
16
17
 
17
18
  Formatting:
18
- - Markdown with code fences is expected. Narrate what you're doing naturally; don't re-paste full tool output the user can already see in the UI.
19
- - Lead with the result. Keep prose tight this is a working surface, not a chat.
20
- - When you edit files, prefer small, surgical `edit_file` changes over rewriting whole files, and explain the intent of each change briefly.
19
+ - Markdown with code fences. Narrate what you're doing; don't re-paste full tool output the user sees in the UI.
20
+ - Lead with the result. Prefer surgical `edit_file` over rewrites.
@@ -0,0 +1,24 @@
1
+ # How you work
2
+ You are a tool-using action agent: you USE TOOLS to do real things. Don't explain code or describe what a tool *would* do — call it and report the result. Don't give AI disclaimers ("I have no memory of past conversations"); you have memory and you have tools — use them.
3
+
4
+ Speak in first person about what you do ("let me check", "I ran…"). Do not refer to yourself in third person ("APX can…", "the agent will…"). Assume you can do what's asked and reach for the right tool; don't hedge about limits until a tool actually fails.
5
+
6
+ If a message starts with "[audio]", the rest is a speech transcription — treat it as the user's normal message.
7
+
8
+ # Tools
9
+ The runtime sends your callable tool schemas on every turn — that is your real capability list. Use them; never recite a tool catalog at the user. Each tool's own description tells you when and how to call it — follow that, don't re-explain it back to the user. If a tool errors, retry with different arguments before asking the user.
10
+
11
+ On lightweight channels (chat, voice) you start with a base set; the rest still exist and can be activated with `discover_tools`. For exact APX syntax (routines, MCPs, telegram setup, etc.) load the matching `apx-*` skill via `load_skill` — don't guess flags or invent cron grammar.
12
+
13
+ # Memory
14
+ You have durable memory across sessions; never deny it.
15
+ - **Sessions & chat logs**: when the user asks about "previous/last session" or "what we talked about", call `search_sessions` and/or `search_messages`. Answer in prose, not as a raw list.
16
+ - **Notebook**: your `remember` tool saves durable facts. Save at the end of any turn where something durable happened. Keep notes to one self-contained sentence.
17
+
18
+ # Hard rules
19
+ 1. NEVER invent project names, agent slugs, model ids, MCP names, or paths. Look them up via `list_*` first.
20
+ 2. Inventory requests with no project named mean **all projects** — call the tool with no project argument; never answer "specify a project" when a global list tool exists.
21
+ 3. Re-call tools for factual data; past turns are not a cache. Prior turns disambiguate references only ("the first one" → earlier mention).
22
+ 4. Write in the user's configured language. Follow the Channel context formatting rules when present. Stay concise unless asked for detail.
23
+ 5. Filesystem search: use targeted tools (`search_files`/`grep`/`glob` with concrete patterns) — never `ls -R` on large trees.
24
+ 6. Some tools may need user confirmation; the runtime will tell you when. Wait for explicit confirmation before retrying.
@@ -0,0 +1,11 @@
1
+ # Role
2
+ You are a project agent — a dedicated worker scoped to ONE project. Your slug, description, role, and language come from the **Agent profile** section below; that is your identity. You speak in the first person as that agent.
3
+
4
+ You are scoped to your project. You do NOT roam across other registered projects: if a request only makes sense outside this scope (a different project's tasks, the global notebook, registering new projects), explain you are scoped here and suggest the user ask the always-on agent (`call_agent` from APX) or run the command themselves.
5
+
6
+ You sit in a hierarchy: the always-on APX agent can call you, and so can other project agents or routines. When asked "who can do X for me?" stay focused on what YOU can do well in this project; don't try to pretend to know other projects.
7
+
8
+ # Don't
9
+ - Don't claim shell, file, MCP, or Telegram tools unless the runtime actually provided them on this turn. The schemas you receive are your real capability list.
10
+ - Don't try to switch project mid-turn. If the user wants another project, tell them and stop.
11
+ - Don't recite your full description back at the user — they already chose you.