@agentprojectcontext/apx 1.34.0 → 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.
- package/package.json +1 -1
- package/skills/apx/SKILL.md +1 -1
- package/src/core/agent/build-agent-system.js +134 -58
- package/src/core/agent/channels/voice-context.js +4 -4
- package/src/core/agent/prompt-builder.js +176 -123
- package/src/core/agent/prompts/channels/code.md +12 -10
- package/src/core/agent/prompts/channels/desktop.md +5 -32
- package/src/core/agent/prompts/channels/telegram.md +4 -15
- package/src/core/agent/prompts/channels/web_code.md +11 -11
- package/src/core/agent/prompts/core/agent-base.md +24 -0
- package/src/core/agent/prompts/core/project-agent.md +11 -0
- package/src/core/agent/prompts/core/super-agent.md +21 -0
- package/src/core/agent/prompts/discipline/action.md +10 -0
- package/src/core/agent/prompts/discipline/single-segment.md +6 -0
- package/src/core/agent/prompts/discipline/two-segment.md +11 -0
- package/src/core/agent/self-memory.js +43 -1
- package/src/core/agent/skills/index-store.js +307 -0
- package/src/core/agent/skills/index.js +15 -1
- package/src/core/agent/skills/inspector.js +317 -0
- package/src/core/agent/super-agent.js +7 -1
- package/src/core/agent/tools/handlers/_git.js +50 -0
- package/src/core/agent/tools/handlers/git-diff.js +44 -0
- package/src/core/agent/tools/handlers/git-log.js +38 -0
- package/src/core/agent/tools/handlers/git-show.js +34 -0
- package/src/core/agent/tools/handlers/git-status.js +61 -0
- package/src/core/agent/tools/names.js +31 -0
- package/src/core/agent/tools/registry.js +36 -5
- package/src/core/config/index.js +21 -0
- package/src/core/runtime-skills/apx/SKILL.md +27 -39
- package/src/core/runtime-skills/apx-agency-agents/SKILL.md +40 -56
- package/src/core/runtime-skills/apx-agent/SKILL.md +27 -30
- package/src/core/runtime-skills/apx-mcp/SKILL.md +31 -36
- package/src/core/runtime-skills/apx-mcp-builder/SKILL.md +37 -51
- package/src/core/runtime-skills/apx-project/SKILL.md +20 -29
- package/src/core/runtime-skills/apx-routine/SKILL.md +34 -47
- package/src/core/runtime-skills/apx-runtime/SKILL.md +32 -50
- package/src/core/runtime-skills/apx-sessions/SKILL.md +96 -145
- package/src/core/runtime-skills/apx-skill-builder/SKILL.md +53 -77
- package/src/core/runtime-skills/apx-task/SKILL.md +18 -21
- package/src/core/runtime-skills/apx-telegram/SKILL.md +43 -54
- package/src/core/runtime-skills/apx-voice/SKILL.md +36 -56
- package/src/host/daemon/api/skills.js +140 -6
- package/src/host/daemon/api/super-agent.js +56 -1
- package/src/host/daemon/index.js +17 -0
- package/src/interfaces/cli/branding.js +53 -0
- package/src/interfaces/cli/commands/skills.js +254 -0
- package/src/interfaces/cli/index.js +84 -2
- package/src/interfaces/web/dist/assets/index-C0fm31dY.js +618 -0
- package/src/interfaces/web/dist/assets/index-C0fm31dY.js.map +1 -0
- package/src/interfaces/web/dist/assets/index-UcAqlBO6.css +1 -0
- package/src/interfaces/web/dist/index.html +2 -2
- package/src/interfaces/web/src/components/chat/MessageBubble.tsx +21 -1
- package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +68 -0
- package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +222 -0
- package/src/interfaces/web/src/hooks/useChat.ts +19 -0
- package/src/interfaces/web/src/i18n/en.ts +1 -0
- package/src/interfaces/web/src/i18n/es.ts +1 -0
- package/src/interfaces/web/src/lib/api/skills.ts +70 -0
- package/src/interfaces/web/src/screens/SettingsScreen.tsx +6 -2
- package/src/interfaces/web/src/types/daemon.ts +10 -0
- package/src/core/agent/prompts/action-discipline.md +0 -24
- package/src/core/agent/prompts/super-agent-base.md +0 -42
- package/src/interfaces/web/dist/assets/index-DdmSRtsz.css +0 -1
- package/src/interfaces/web/dist/assets/index-M4FspaCH.js +0 -613
- package/src/interfaces/web/dist/assets/index-M4FspaCH.js.map +0 -1
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: apx-mcp
|
|
3
|
-
description:
|
|
3
|
+
description: Register, list, debug, scope MCP servers in APX. Load BEFORE adding any MCP — three scopes (shared/runtime/global) with different commit and secrecy semantics. Triggers: 'add MCP', 'apx mcp', 'MCP scope', 'MCP failing', 'list MCPs'.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# apx-mcp
|
|
7
7
|
|
|
8
|
-
APX exposes
|
|
8
|
+
APX exposes MCP servers via three scopes; resolution priority **runtime > shared > global**, conflicts via `apx mcp check`:
|
|
9
9
|
|
|
10
10
|
| Scope | File | Committed? | Secrets OK? | When |
|
|
11
11
|
|---|---|---|---|---|
|
|
12
|
-
| `shared` | `<repo>/.apc/mcps.json` | yes | **no** | Team-wide
|
|
13
|
-
| `runtime` | `~/.apx/projects/<apxId>/mcps.json` (chmod 0600) | no | yes | Per-project
|
|
14
|
-
| `global` | `~/.apx/mcps.json` | n/a | yes | Machine-wide
|
|
15
|
-
|
|
16
|
-
Resolution priority when a name appears in more than one: **runtime > shared > global**. Conflicts surface in `apx mcp check`.
|
|
12
|
+
| `shared` | `<repo>/.apc/mcps.json` | yes | **no** | Team-wide (filesystem, brave, github public) |
|
|
13
|
+
| `runtime` | `~/.apx/projects/<apxId>/mcps.json` (chmod 0600) | no | yes | Per-project — tokens, machine-specific endpoints |
|
|
14
|
+
| `global` | `~/.apx/mcps.json` | n/a | yes | Machine-wide, not tied to a project |
|
|
17
15
|
|
|
18
16
|
## Concrete CLI calls
|
|
19
17
|
|
|
20
18
|
```bash
|
|
21
|
-
# List (all scopes
|
|
19
|
+
# List (defaults to all scopes)
|
|
22
20
|
apx mcp list --project iacrmar
|
|
23
21
|
apx mcp list --scope runtime --project iacrmar
|
|
24
22
|
apx mcp list --scope shared --project iacrmar
|
|
@@ -36,34 +34,32 @@ apx mcp add github --scope runtime --project iacrmar \
|
|
|
36
34
|
--command npx --env GITHUB_TOKEN=ghp_xxx \
|
|
37
35
|
-- -y @modelcontextprotocol/server-github
|
|
38
36
|
|
|
39
|
-
# Add — global (machine-wide
|
|
37
|
+
# Add — global (machine-wide)
|
|
40
38
|
apx mcp add brave --scope global \
|
|
41
39
|
--command npx --env BRAVE_API_KEY=BSAxxx \
|
|
42
40
|
-- -y @modelcontextprotocol/server-brave-search
|
|
43
41
|
|
|
44
|
-
# Remove (pass --scope when
|
|
45
|
-
# shared inside an APC project, else global)
|
|
42
|
+
# Remove (pass --scope when not in default: shared inside APC project, else global)
|
|
46
43
|
apx mcp remove filesystem --project iacrmar
|
|
47
44
|
apx mcp remove github --scope runtime --project iacrmar
|
|
48
45
|
|
|
49
|
-
# Toggle (defaults to
|
|
46
|
+
# Toggle (defaults to owning scope)
|
|
50
47
|
apx mcp enable filesystem --project iacrmar
|
|
51
48
|
apx mcp disable filesystem --project iacrmar
|
|
52
49
|
|
|
53
|
-
# Call a tool through the daemon (
|
|
50
|
+
# Call a tool through the daemon (debugging)
|
|
54
51
|
apx mcp run filesystem read_file '{"path":"README.md"}'
|
|
55
52
|
```
|
|
56
53
|
|
|
57
|
-
##
|
|
54
|
+
## Scope decision tree
|
|
58
55
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
2. **Is part of the project's shared dev environment?** → `shared` (committed).
|
|
56
|
+
1. **Has secrets/tokens?** → `runtime`. Always.
|
|
57
|
+
2. **Part of project's shared dev environment?** → `shared` (committed).
|
|
62
58
|
3. **Used across all your projects?** → `global`.
|
|
63
59
|
|
|
64
|
-
Default if
|
|
60
|
+
Default if unclear: `shared` inside an APC project, `global` outside.
|
|
65
61
|
|
|
66
|
-
##
|
|
62
|
+
## Command shapes by transport
|
|
67
63
|
|
|
68
64
|
```bash
|
|
69
65
|
# stdio MCP (most common — npx, uvx, node, python)
|
|
@@ -78,39 +74,38 @@ apx mcp add <name> --command npx \
|
|
|
78
74
|
-- -y @modelcontextprotocol/server-github
|
|
79
75
|
```
|
|
80
76
|
|
|
81
|
-
|
|
77
|
+
Everything after `--` is forwarded verbatim as args. Quote carefully.
|
|
82
78
|
|
|
83
79
|
## Anti-examples
|
|
84
80
|
|
|
85
81
|
```bash
|
|
86
|
-
# DON'T put tokens in shared scope
|
|
82
|
+
# DON'T put tokens in shared scope — it commits.
|
|
87
83
|
apx mcp add github --scope shared --env GITHUB_TOKEN=ghp_xxx ...
|
|
88
84
|
# ↑ Token ends up in .apc/mcps.json in your repo. Use --scope runtime.
|
|
89
85
|
|
|
90
|
-
# DON'T remove
|
|
91
|
-
apx mcp remove github # if github lives in runtime
|
|
92
|
-
# ↑ Daemon returns 409 with the right scope to use.
|
|
86
|
+
# DON'T remove from the wrong scope — daemon returns 409 with the right scope.
|
|
87
|
+
apx mcp remove github # errors if github lives in runtime
|
|
93
88
|
|
|
94
|
-
# DON'T expect IDE-foreign configs (~/.cursor/mcps.json, ~/.claude/mcps.json)
|
|
95
|
-
# removable via apx mcp remove. APX reads them
|
|
89
|
+
# DON'T expect IDE-foreign configs (~/.cursor/mcps.json, ~/.claude/mcps.json)
|
|
90
|
+
# to be removable via apx mcp remove. APX reads them advisory (source=cursor/claude)
|
|
96
91
|
# but won't write them. Edit the IDE config directly.
|
|
97
92
|
```
|
|
98
93
|
|
|
99
|
-
## Debugging
|
|
94
|
+
## Debugging
|
|
100
95
|
|
|
101
96
|
```bash
|
|
102
|
-
apx mcp check --project iacrmar
|
|
103
|
-
apx mcp run <name> <tool> '{...}'
|
|
104
|
-
apx log -f
|
|
97
|
+
apx mcp check --project iacrmar # scopes seen + which files exist
|
|
98
|
+
apx mcp run <name> <tool> '{...}' # spawn server, call a tool
|
|
99
|
+
apx log -f # tail unified log for spawn errors
|
|
105
100
|
```
|
|
106
101
|
|
|
107
|
-
|
|
102
|
+
"Doesn't show tools" = command failed to start (missing env vars, package not found) or crashed during initialize. Unified log holds the stderr buffer.
|
|
108
103
|
|
|
109
|
-
> `apx mcp tools <name>` is a placeholder stub (
|
|
104
|
+
> `apx mcp tools <name>` is a placeholder stub ("coming in v0.2"). Use `apx mcp run` to verify spawn.
|
|
110
105
|
|
|
111
106
|
## Don't
|
|
112
107
|
|
|
113
|
-
- Don't mix scopes for the same MCP name unless you
|
|
114
|
-
- Don't edit `~/.apx/projects/<id>/mcps.json` by hand; use `apx mcp add --scope runtime
|
|
115
|
-
- Don't
|
|
116
|
-
- Don't forget to `apx daemon reload` after editing
|
|
108
|
+
- Don't mix scopes for the same MCP name unless you want shadowing — highest priority wins, others stay invisible.
|
|
109
|
+
- Don't edit `~/.apx/projects/<id>/mcps.json` by hand; use `apx mcp add --scope runtime` (the file is chmod 0600 — CLI preserves it).
|
|
110
|
+
- Don't put tokens via `--env KEY=` inline if shell history is public. Set them in your shell first, then `--env KEY=$KEY`.
|
|
111
|
+
- Don't forget to `apx daemon reload` after hand-editing JSON. `apx mcp` does this for you.
|
|
@@ -1,33 +1,31 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: apx-mcp-builder
|
|
3
3
|
scope: internal
|
|
4
|
-
description:
|
|
4
|
+
description: Author a new MCP (Model Context Protocol) server and register it in APX. Covers JSON-RPC stdio protocol, FastMCP (Python) / TypeScript SDK shapes, tool design, secrets, debugging. Load when building a new MCP / exposing a new tool surface. To add an existing MCP, load `apx-mcp` instead.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# apx-mcp-builder
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
An MCP server is a tiny stdio JSON-RPC process. APX spawns it (via `apx mcp add`), discovers tools (`tools/list`), and lets the super-agent call them by name.
|
|
10
10
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
An MCP server must implement four RPC methods:
|
|
11
|
+
## Minimum surface
|
|
14
12
|
|
|
15
13
|
| Method | Purpose | Returns |
|
|
16
14
|
|---|---|---|
|
|
17
|
-
| `initialize` | Handshake
|
|
18
|
-
| `tools/list` | Enumerate
|
|
19
|
-
| `tools/call` | Run one tool
|
|
20
|
-
| `notifications/initialized` | One-way
|
|
15
|
+
| `initialize` | Handshake (protocol version + capabilities). | Server capabilities. |
|
|
16
|
+
| `tools/list` | Enumerate tools. | `{ tools: [{name, description, inputSchema}] }` |
|
|
17
|
+
| `tools/call` | Run one tool with `{ name, arguments }`. | `{ content: [...], isError? }` |
|
|
18
|
+
| `notifications/initialized` | One-way init-done from APX. | — |
|
|
21
19
|
|
|
22
|
-
JSON-RPC 2.0
|
|
20
|
+
JSON-RPC 2.0 over stdio, framed `Content-Length: N\r\n\r\n<JSON>`. The `@modelcontextprotocol/sdk` (TS) and `fastmcp` / `mcp` (Python) packages handle framing.
|
|
23
21
|
|
|
24
22
|
## Pick a stack
|
|
25
23
|
|
|
26
24
|
| Stack | When |
|
|
27
25
|
|---|---|
|
|
28
|
-
| **Python + FastMCP** | Fastest path
|
|
29
|
-
| **Node + @modelcontextprotocol/sdk** |
|
|
30
|
-
| Raw JSON-RPC | Only
|
|
26
|
+
| **Python + FastMCP** | Fastest path; decorator-based; ideal for pip-wrapping tools. |
|
|
27
|
+
| **Node + @modelcontextprotocol/sdk** | Node-only libs, or zero install (`npx -y`). |
|
|
28
|
+
| Raw JSON-RPC | Only when exposing an existing daemon. Otherwise use the SDK. |
|
|
31
29
|
|
|
32
30
|
## Python (FastMCP) — minimum viable server
|
|
33
31
|
|
|
@@ -40,7 +38,6 @@ mcp = FastMCP("my-server")
|
|
|
40
38
|
@mcp.tool()
|
|
41
39
|
def search_inventory(query: str, limit: int = 10) -> list[dict]:
|
|
42
40
|
"""Search the inventory by free-text query. Returns matching SKUs."""
|
|
43
|
-
# ... your logic ...
|
|
44
41
|
return [{"sku": "abc", "title": "..."}]
|
|
45
42
|
|
|
46
43
|
@mcp.tool()
|
|
@@ -49,18 +46,13 @@ def get_stock(sku: str) -> dict:
|
|
|
49
46
|
return {"sku": sku, "stock": 42}
|
|
50
47
|
|
|
51
48
|
if __name__ == "__main__":
|
|
52
|
-
mcp.run() # stdio transport
|
|
49
|
+
mcp.run() # stdio transport
|
|
53
50
|
```
|
|
54
51
|
|
|
55
|
-
Install:
|
|
56
52
|
```bash
|
|
57
53
|
pip install fastmcp
|
|
58
|
-
# or
|
|
59
|
-
uv tool install fastmcp
|
|
60
|
-
```
|
|
54
|
+
# or: uv tool install fastmcp
|
|
61
55
|
|
|
62
|
-
Register in APX:
|
|
63
|
-
```bash
|
|
64
56
|
apx mcp add my-server \
|
|
65
57
|
--command uv --project iacrmar \
|
|
66
58
|
-- run python /abs/path/my_server.py
|
|
@@ -102,7 +94,6 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
102
94
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
103
95
|
if (req.params.name === "search_inventory") {
|
|
104
96
|
const { query, limit = 10 } = req.params.arguments as any;
|
|
105
|
-
// ... your logic ...
|
|
106
97
|
return {
|
|
107
98
|
content: [{ type: "text", text: JSON.stringify([{ sku: "abc" }]) }],
|
|
108
99
|
};
|
|
@@ -113,7 +104,6 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
113
104
|
await server.connect(new StdioServerTransport());
|
|
114
105
|
```
|
|
115
106
|
|
|
116
|
-
Register:
|
|
117
107
|
```bash
|
|
118
108
|
apx mcp add my-server \
|
|
119
109
|
--command npx --project iacrmar \
|
|
@@ -122,16 +112,14 @@ apx mcp add my-server \
|
|
|
122
112
|
|
|
123
113
|
## Tool design rules
|
|
124
114
|
|
|
125
|
-
1. **Names are snake_case
|
|
126
|
-
2. **inputSchema is JSON Schema draft-07**.
|
|
127
|
-
3. **Descriptions read like a
|
|
128
|
-
4. **Return structured data**, not prose.
|
|
129
|
-
5. **Errors are errors
|
|
115
|
+
1. **Names are snake_case verbs**: `search_inventory`, not `inventorySearch`.
|
|
116
|
+
2. **inputSchema is JSON Schema draft-07**. `required` matters — vague schemas → bad calls.
|
|
117
|
+
3. **Descriptions read like a man-page**. Tool + param descriptions are surfaced to the model.
|
|
118
|
+
4. **Return structured data**, not prose. Convention: JSON inside a text content block. Images use the `image` type.
|
|
119
|
+
5. **Errors are errors**: `throw new Error(...)` propagates as `isError: true`. Empty result = "found nothing" — different signal.
|
|
130
120
|
|
|
131
121
|
## Env vars and secrets
|
|
132
122
|
|
|
133
|
-
Pass them at registration time via `--env`:
|
|
134
|
-
|
|
135
123
|
```bash
|
|
136
124
|
apx mcp add github \
|
|
137
125
|
--scope runtime --project iacrmar \
|
|
@@ -141,43 +129,41 @@ apx mcp add github \
|
|
|
141
129
|
-- -y @modelcontextprotocol/server-github
|
|
142
130
|
```
|
|
143
131
|
|
|
144
|
-
`--scope runtime` writes to `~/.apx/projects/<id>/mcps.json` (chmod 0600, never committed). NEVER
|
|
132
|
+
`--scope runtime` writes to `~/.apx/projects/<id>/mcps.json` (chmod 0600, never committed). NEVER `--scope shared` for tokens — that file lives in `.apc/` and gets committed.
|
|
145
133
|
|
|
146
134
|
## Anti-examples
|
|
147
135
|
|
|
148
136
|
```python
|
|
149
|
-
# DON'T expose every internal function
|
|
150
|
-
#
|
|
151
|
-
# tools per server; split into multiple servers if you have more.
|
|
137
|
+
# DON'T expose every internal function. A server with 40 tools eats context.
|
|
138
|
+
# Pick 5-10 high-value tools per server; split into multiple servers if more.
|
|
152
139
|
|
|
153
|
-
# DON'T return giant blobs in `content`. The agent
|
|
154
|
-
#
|
|
140
|
+
# DON'T return giant blobs in `content`. The agent re-reads every turn.
|
|
141
|
+
# Paginate (`offset`, `limit`) and let the agent ask for more.
|
|
155
142
|
|
|
156
|
-
# DON'T mix stdio + HTTP transports in
|
|
157
|
-
#
|
|
158
|
-
# of `command:`.
|
|
143
|
+
# DON'T mix stdio + HTTP transports in one process. APX spawns stdio;
|
|
144
|
+
# for HTTP use `url:` in mcps.json instead of `command:`.
|
|
159
145
|
|
|
160
|
-
# DON'T print to stdout
|
|
161
|
-
#
|
|
162
|
-
#
|
|
146
|
+
# DON'T print to stdout outside JSON-RPC frames. Stray print() corrupts
|
|
147
|
+
# the protocol — use stderr for logs. (SDKs handle this; bare `print("debug")`
|
|
148
|
+
# in a tool body breaks everything.)
|
|
163
149
|
```
|
|
164
150
|
|
|
165
|
-
##
|
|
151
|
+
## Debugging
|
|
166
152
|
|
|
167
153
|
```bash
|
|
168
|
-
#
|
|
154
|
+
# Smoke test (apx mcp tools is a v0.2 stub — don't rely on it)
|
|
169
155
|
apx mcp run my-server search_inventory '{"query":"shoes"}'
|
|
170
156
|
|
|
171
|
-
#
|
|
172
|
-
apx log -f
|
|
157
|
+
# Spawn errors / stderr
|
|
158
|
+
apx log -f
|
|
173
159
|
|
|
174
|
-
#
|
|
160
|
+
# Scopes / files / env APX sees
|
|
175
161
|
apx mcp check --project iacrmar
|
|
176
162
|
```
|
|
177
163
|
|
|
178
164
|
## Don't
|
|
179
165
|
|
|
180
|
-
- Don't reinvent
|
|
181
|
-
- Don't make
|
|
182
|
-
- Don't ship
|
|
183
|
-
- Don't expect APX to retry MCP errors
|
|
166
|
+
- Don't reinvent SDK framing — bypass only with reason.
|
|
167
|
+
- Don't make interactive tools. MCP is one-shot per call; split flows into multiple tools.
|
|
168
|
+
- Don't ship without a README — future-you forgets which env vars matter.
|
|
169
|
+
- Don't expect APX to retry MCP errors. The agent sees the error and decides.
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: apx-project
|
|
3
|
-
description:
|
|
3
|
+
description: Register, list, configure, manage APX projects. Load BEFORE asking "which project?" — registered projects are listable; per-project config set via dotted-key PATCH. Triggers: 'register project', 'apx project', 'project config', 'list projects', 'what projects are registered'.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# apx-project
|
|
7
7
|
|
|
8
|
-
A project in APX is an APC-compliant folder
|
|
8
|
+
A project in APX is an APC-compliant folder (`AGENTS.md` + `.apc/project.json`). Once registered, APX keeps runtime state (sessions, messages, routines, tasks, MCPs) under `~/.apx/projects/<apxId>/`.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Two kinds of projects
|
|
11
11
|
|
|
12
|
-
- **`default`** (id=0):
|
|
12
|
+
- **`default`** (id=0): super-agent's scratch workspace at `~/.apx/projects/default/`. Used when user has no project named, no project registered, or addresses "apx itself". Don't use for real work — shared.
|
|
13
13
|
- **registered** (id=1+): real projects, each rooted at a path the user owns.
|
|
14
14
|
|
|
15
15
|
## Concrete CLI calls
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
# Register
|
|
19
|
-
apx project add /path/to/repo #
|
|
19
|
+
apx project add /path/to/repo # reads AGENTS.md + .apc/project.json
|
|
20
20
|
apx project add . # current dir
|
|
21
21
|
|
|
22
22
|
# Inspect
|
|
23
23
|
apx project list # id, name, agents count, path
|
|
24
24
|
|
|
25
|
-
# Remove / rebuild (id or exact path only —
|
|
25
|
+
# Remove / rebuild (id or exact path only — no name resolution here)
|
|
26
26
|
apx project remove <id|path>
|
|
27
|
-
apx project rebuild <id|path> # force re-scan of .apc/
|
|
27
|
+
apx project rebuild <id|path> # force re-scan of .apc/
|
|
28
28
|
|
|
29
29
|
# Per-project config — dotted keys, lives in <repo>/.apc/config.json
|
|
30
30
|
apx project config show <project> # effective + project_only
|
|
@@ -36,17 +36,11 @@ apx project config unset <project> super_agent.model # back to glo
|
|
|
36
36
|
apx project config edit <project> # opens $EDITOR on project_only JSON
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Every
|
|
39
|
+
Every `project config` write triggers `POST /admin/reload` so the daemon picks up changes without restart.
|
|
40
40
|
|
|
41
|
-
##
|
|
41
|
+
## `<project>` argument resolution
|
|
42
42
|
|
|
43
|
-
Accepted
|
|
44
|
-
- numeric id: `1`
|
|
45
|
-
- exact name from `.apc/project.json`: `iacrmar`
|
|
46
|
-
- absolute path: `/Volumes/SSDT7Shield/trabajos_proyectos/iacrmar`
|
|
47
|
-
- relative path (from cwd) — resolved before matching.
|
|
48
|
-
|
|
49
|
-
The CLI calls `resolveProjectId()` which does fuzzy id-or-name-or-path matching. If you got "project not found", `apx project list` first.
|
|
43
|
+
Accepted: numeric id (`1`), exact name from `.apc/project.json` (`iacrmar`), absolute path, relative path (resolved from cwd). The CLI's `resolveProjectId()` does fuzzy id/name/path matching. If "project not found", run `apx project list` first.
|
|
50
44
|
|
|
51
45
|
## What lives where
|
|
52
46
|
|
|
@@ -59,7 +53,7 @@ The CLI calls `resolveProjectId()` which does fuzzy id-or-name-or-path matching.
|
|
|
59
53
|
├── skills/<slug>.md or <slug>/SKILL.md
|
|
60
54
|
├── mcps.json ← shared MCPs (committed)
|
|
61
55
|
├── commands/ ← custom slash-commands
|
|
62
|
-
└── config.json ← project-only overrides (
|
|
56
|
+
└── config.json ← project-only overrides (edited by `project config`)
|
|
63
57
|
|
|
64
58
|
~/.apx/projects/<apxId>/ ← runtime state (never committed)
|
|
65
59
|
├── messages/YYYY-MM-DD.jsonl
|
|
@@ -70,29 +64,26 @@ The CLI calls `resolveProjectId()` which does fuzzy id-or-name-or-path matching.
|
|
|
70
64
|
└── mcps.json ← per-project runtime MCPs (local, may hold tokens)
|
|
71
65
|
```
|
|
72
66
|
|
|
73
|
-
## Anti-
|
|
67
|
+
## Anti-examples
|
|
74
68
|
|
|
75
69
|
```bash
|
|
76
70
|
# DON'T hand-write AGENTS.md + .apc/project.json with shell tools.
|
|
77
71
|
echo "Hello" > /path/repo/AGENTS.md
|
|
78
|
-
mkdir -p /path/repo/.apc
|
|
79
|
-
|
|
80
|
-
|
|
72
|
+
mkdir -p /path/repo/.apc && echo "{...}" > /path/repo/.apc/project.json
|
|
73
|
+
# ↑ No scaffold validation; project appears registered but breaks on `apx project rebuild`.
|
|
74
|
+
# Use `apx init <path>` then `apx project add <path>`.
|
|
81
75
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
# DON'T set super_agent.model to a model that's not in the engine you have keys for.
|
|
76
|
+
# DON'T set super_agent.model to a model lacking an engine key.
|
|
86
77
|
apx project config set iacrmar super_agent.model gemini:gemini-1.5-pro
|
|
87
|
-
# ↑
|
|
78
|
+
# ↑ Fails at first call unless engines.gemini.api_key is set.
|
|
88
79
|
```
|
|
89
80
|
|
|
90
81
|
## When asked "what projects are there?"
|
|
91
82
|
|
|
92
|
-
Don't ask
|
|
83
|
+
Don't ask — call `list_projects` tool or `apx project list`. Same for "which agents does X have?" → `list_agents` / `apx agent list --project X`.
|
|
93
84
|
|
|
94
85
|
## Don't
|
|
95
86
|
|
|
96
|
-
- Don't operate on the default project (id=0) as if it were the user's main work.
|
|
87
|
+
- Don't operate on the default project (id=0) as if it were the user's main work. Scratch space for super-agent state.
|
|
97
88
|
- Don't put secrets in `.apc/config.json` — it's committed. Put them in `~/.apx/config.json` (machine-local) under `engines.*` or `voice.tts.*`.
|
|
98
|
-
- Don't move a project's `.apc/` folder without re-running `apx project rebuild`
|
|
89
|
+
- Don't move a project's `.apc/` folder without re-running `apx project rebuild` — `apxId` will be stale.
|
|
@@ -1,35 +1,31 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: apx-routine
|
|
3
|
-
description:
|
|
3
|
+
description: Create, edit, run, debug APX routines (scheduled tasks). Load BEFORE `apx routine add` — schedule grammar, kind selection, pre/post hooks, double-reply gotcha.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# apx-routine
|
|
7
7
|
|
|
8
|
-
A
|
|
8
|
+
A scheduled APX task. Scheduler ticks every 5s. Each routine has a `kind`, `schedule`, optional `spec`, and optional `pre_commands` / `post_commands` shell hooks.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Picking `kind`
|
|
11
11
|
|
|
12
12
|
| Kind | Tools? | Description |
|
|
13
13
|
|---|---|---|
|
|
14
|
-
| `heartbeat` | no |
|
|
15
|
-
| `shell` | no | Pure shell
|
|
16
|
-
| `exec_agent` | **no
|
|
17
|
-
| `super_agent` | **all
|
|
18
|
-
| `telegram` | n/a | Sends
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- Just need text from a model? → `exec_agent`.
|
|
22
|
-
- Need orchestration (call MCPs, write files, call other agents, send messages with logic)? → `super_agent`.
|
|
23
|
-
- Pure shell (curl + jq + write somewhere)? → `shell`.
|
|
24
|
-
- Periodic Telegram poke with fixed text? → `telegram`.
|
|
14
|
+
| `heartbeat` | no | "Still alive" marker. No LLM. |
|
|
15
|
+
| `shell` | no | Pure shell. Stdout captured. |
|
|
16
|
+
| `exec_agent` | **no** | Loads agent prompt, sends `spec.prompt`, returns text. Single LLM call. |
|
|
17
|
+
| `super_agent` | **all** | Default agent with full tool registry. Multi-iteration loop. |
|
|
18
|
+
| `telegram` | n/a | Sends hardcoded text via Telegram plugin. |
|
|
19
|
+
|
|
20
|
+
Rule: text from model → `exec_agent`; orchestration (MCPs, files, multi-agent) → `super_agent`; pure shell → `shell`; fixed Telegram poke → `telegram`.
|
|
25
21
|
|
|
26
22
|
## Schedule grammar
|
|
27
23
|
|
|
28
24
|
- `every:<N><unit>` — `every:30s`, `every:5m`, `every:24h`, `every:7d`. **Most common.**
|
|
29
|
-
- `once:<iso-8601>` — `once:2026-12-01T08:00:00Z`. Fires once
|
|
30
|
-
- Cron — `*/5 * * * *`, `0 8 * * *`. Standard 5-field.
|
|
25
|
+
- `once:<iso-8601>` — `once:2026-12-01T08:00:00Z`. Fires once, then disabled.
|
|
26
|
+
- Cron — `*/5 * * * *`, `0 8 * * *`. Standard 5-field.
|
|
31
27
|
|
|
32
|
-
## Anatomy
|
|
28
|
+
## Anatomy
|
|
33
29
|
|
|
34
30
|
```json
|
|
35
31
|
{
|
|
@@ -44,12 +40,9 @@ A routine is a scheduled APX task. APX runs the scheduler tick every 5s and fire
|
|
|
44
40
|
}
|
|
45
41
|
```
|
|
46
42
|
|
|
47
|
-
|
|
48
|
-
1. `pre_commands` run sequentially. Their combined stdout becomes `{{pre_output}}` substitutable in `spec.prompt`, and `$APX_PRE_OUTPUT` env var available to `post_commands`. Also written to `$APX_PRE_OUTPUT_FILE` for big payloads.
|
|
49
|
-
2. The handler for `kind` runs. Its text result is exposed to post hooks as `$APX_LLM_OUTPUT`.
|
|
50
|
-
3. `post_commands` run sequentially with that env.
|
|
43
|
+
Pipeline: `pre_commands` run sequentially → combined stdout becomes `{{pre_output}}` in `spec.prompt` and `$APX_PRE_OUTPUT` (plus `$APX_PRE_OUTPUT_FILE` for big payloads) → handler runs, result becomes `$APX_LLM_OUTPUT` → `post_commands` run.
|
|
51
44
|
|
|
52
|
-
## Anti-example:
|
|
45
|
+
## Anti-example: double-reply
|
|
53
46
|
|
|
54
47
|
```json
|
|
55
48
|
{
|
|
@@ -59,28 +52,24 @@ A routine is a scheduled APX task. APX runs the scheduler tick every 5s and fire
|
|
|
59
52
|
}
|
|
60
53
|
```
|
|
61
54
|
|
|
62
|
-
|
|
55
|
+
Sends **two** messages: one from agent's `send_telegram` tool, one from `post_commands`. The runner auto-suppresses `send_telegram` when post contains `apx telegram send`, but the clean fix is `exec_agent`:
|
|
63
56
|
|
|
64
57
|
```json
|
|
65
58
|
{
|
|
66
59
|
"kind": "exec_agent",
|
|
67
|
-
"spec": { "agent": "default", "prompt": "The weather is {{pre_output}}. One friendly sentence
|
|
60
|
+
"spec": { "agent": "default", "prompt": "The weather is {{pre_output}}. One friendly sentence." },
|
|
68
61
|
"post_commands": ["apx telegram send \"$APX_LLM_OUTPUT\""]
|
|
69
62
|
}
|
|
70
63
|
```
|
|
71
64
|
|
|
72
|
-
One message, the model writes prose, the shell pipes it to Telegram.
|
|
73
|
-
|
|
74
65
|
## Concrete CLI calls
|
|
75
66
|
|
|
76
67
|
```bash
|
|
77
|
-
#
|
|
68
|
+
# Always pin --project; never use default for real ones
|
|
78
69
|
apx routine list --project iacrmar
|
|
70
|
+
apx routine get weather-bariloche --project iacrmar
|
|
79
71
|
|
|
80
|
-
#
|
|
81
|
-
apx routine get weather-bariloche --project iacrmar
|
|
82
|
-
|
|
83
|
-
# Create — text-only exec_agent + shell delivery
|
|
72
|
+
# Create — exec_agent + shell delivery
|
|
84
73
|
apx routine add weather-bariloche \
|
|
85
74
|
--project iacrmar \
|
|
86
75
|
--kind exec_agent \
|
|
@@ -97,7 +86,7 @@ apx routine add daily-status \
|
|
|
97
86
|
--spec '{"prompt":"List projects with pending tasks and send me a short summary via Telegram."}' \
|
|
98
87
|
--permission-mode automatico
|
|
99
88
|
|
|
100
|
-
# Toggle
|
|
89
|
+
# Toggle / run / remove
|
|
101
90
|
apx routine enable weather-bariloche --project iacrmar
|
|
102
91
|
apx routine disable weather-bariloche --project iacrmar
|
|
103
92
|
apx routine run weather-bariloche --project iacrmar # force-trigger now
|
|
@@ -106,23 +95,21 @@ apx routine remove weather-bariloche --project iacrmar
|
|
|
106
95
|
|
|
107
96
|
## `--project` is non-negotiable
|
|
108
97
|
|
|
109
|
-
Routines live in `~/.apx/projects/<apxId>/routines.json`. Without `--project`,
|
|
98
|
+
Routines live in `~/.apx/projects/<apxId>/routines.json`. Without `--project`, they go to default (id=0, super-agent scratch) — **not** a user project. Always pass `--project <name|id|path>`.
|
|
110
99
|
|
|
111
100
|
## `skip_prompt_on`
|
|
112
101
|
|
|
113
|
-
|
|
102
|
+
Gates the LLM call based on `pre_commands` (`shouldSkipPrompt` in `host/daemon/routines.js`). Post-commands always run.
|
|
114
103
|
|
|
115
|
-
| Value | Skips
|
|
104
|
+
| Value | Skips LLM when… |
|
|
116
105
|
|---|---|
|
|
117
|
-
| `signal` (default) |
|
|
106
|
+
| `signal` (default) | pre_command prints literal `APX_SKIP`. Non-zero exit alone does NOT skip. |
|
|
118
107
|
| `pre_failure` | any pre_command exits non-zero. |
|
|
119
|
-
| `pre_success` |
|
|
120
|
-
| `always` | unconditionally — pure pre→post
|
|
121
|
-
| `never` |
|
|
122
|
-
|
|
123
|
-
Post-commands run regardless of the skip decision. The skip only gates the `kind` handler (the LLM call).
|
|
108
|
+
| `pre_success` | pre_commands exit 0 (LLM only on pre failure). |
|
|
109
|
+
| `always` | unconditionally — pure pre→post, no LLM. |
|
|
110
|
+
| `never` | LLM always runs, even if pre crashes. |
|
|
124
111
|
|
|
125
|
-
## Debugging
|
|
112
|
+
## Debugging
|
|
126
113
|
|
|
127
114
|
```bash
|
|
128
115
|
apx routine history weather-bariloche --project iacrmar # last runs
|
|
@@ -130,11 +117,11 @@ apx log -f # tail unified log
|
|
|
130
117
|
apx messages tail --channel routine -n 20 # routine-channel messages
|
|
131
118
|
```
|
|
132
119
|
|
|
133
|
-
|
|
120
|
+
"Sends nothing" usually means: `enabled: false`, `next_run_at` in the future, or empty LLM text (check `apx messages` or `result.text`).
|
|
134
121
|
|
|
135
122
|
## Don't
|
|
136
123
|
|
|
137
|
-
-
|
|
138
|
-
-
|
|
139
|
-
-
|
|
140
|
-
-
|
|
124
|
+
- Use `super_agent` when `exec_agent` would do — it loops, calls tools, costs more.
|
|
125
|
+
- Write `apx telegram send` inside a `super_agent` prompt — agent calls `send_telegram` AND post_commands fire. Pick one.
|
|
126
|
+
- Hardcode model names in `spec` without reason — routines inherit `super_agent.model` (with router fallback).
|
|
127
|
+
- Put credentials in `spec`. Use `~/.apx/config.json` engines and reference by provider.
|