agents-dojo 0.1.8 → 0.1.10
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/README.md +63 -3
- package/dist/agent-loader.js +31 -5
- package/dist/claude-bridge.js +9 -4
- package/dist/cli.js +103 -9
- package/dist/context-manager.d.ts +1 -1
- package/dist/context-manager.js +4 -3
- package/dist/manifest-schema.d.ts +1 -1
- package/dist/manifest-schema.js +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,13 +15,55 @@ agents-dojo init
|
|
|
15
15
|
agents-dojo
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
## Creating Agents
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
Each agent lives in its own directory under `agents/`. The only required file is `manifest.jsonc`.
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
agents/my-agent/
|
|
24
|
+
├── manifest.jsonc # required — agent identity, model, A2A card
|
|
25
|
+
├── context.md # optional — custom system prompt
|
|
26
|
+
└── CLAUDE.md # optional — extra rules and constraints
|
|
27
|
+
```
|
|
22
28
|
|
|
23
29
|
See `agents/_template_echo/` for a complete manifest reference.
|
|
24
30
|
|
|
31
|
+
### context.md — Custom System Prompt
|
|
32
|
+
|
|
33
|
+
`context.md` controls the agent's system prompt:
|
|
34
|
+
|
|
35
|
+
- **Without `context.md`**: The agent uses Claude Code's built-in default system
|
|
36
|
+
prompt. This is ideal for **code-related agents** — they get full programming
|
|
37
|
+
capabilities (file editing, bash, code analysis, etc.) out of the box.
|
|
38
|
+
|
|
39
|
+
- **With `context.md`**: The file content **replaces** the default system prompt
|
|
40
|
+
entirely. Use this for agents whose role has **nothing to do with coding** —
|
|
41
|
+
e.g. a chef, poet, or customer support agent. You define the persona, behavior
|
|
42
|
+
rules, and output format from scratch.
|
|
43
|
+
|
|
44
|
+
### CLAUDE.md — Extra Rules and Constraints
|
|
45
|
+
|
|
46
|
+
`CLAUDE.md` is loaded automatically by the Claude Code SDK (not by AgentsDojo).
|
|
47
|
+
It **appends** to whatever system prompt is active — whether the default or a
|
|
48
|
+
custom `context.md`.
|
|
49
|
+
|
|
50
|
+
Use `CLAUDE.md` for:
|
|
51
|
+
- Project-specific rules ("always use TypeScript", "never delete files")
|
|
52
|
+
- Coding conventions and style guides
|
|
53
|
+
- Build/test commands the agent should know about
|
|
54
|
+
- Safety constraints and guardrails
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
agents/code-reviewer/
|
|
58
|
+
├── manifest.jsonc # identity
|
|
59
|
+
└── CLAUDE.md # "Review for security issues. Run `npm test` after changes."
|
|
60
|
+
|
|
61
|
+
agents/poet/
|
|
62
|
+
├── manifest.jsonc # identity
|
|
63
|
+
├── context.md # "You are Poet Luna, a lyrical poet..."
|
|
64
|
+
└── CLAUDE.md # "Always respond in English. Keep poems under 20 lines."
|
|
65
|
+
```
|
|
66
|
+
|
|
25
67
|
## Monitor GUI
|
|
26
68
|
|
|
27
69
|
The Monitor GUI starts automatically when you run `agents-dojo`. It picks a free
|
|
@@ -34,6 +76,24 @@ agents-dojo --monitor-port=9000 # use a specific WS port
|
|
|
34
76
|
agents-dojo --no-monitor # disable the monitor
|
|
35
77
|
```
|
|
36
78
|
|
|
79
|
+
## Chat with Agents
|
|
80
|
+
|
|
81
|
+
Users can talk to agents via btw-style one-shot chat. This forks the agent's
|
|
82
|
+
current session (preserving context), disables all tools (text-only reply), and
|
|
83
|
+
discards the fork afterward — the main session is never affected.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# CLI
|
|
87
|
+
agents-dojo chat <agentId> <message>
|
|
88
|
+
|
|
89
|
+
# REST API
|
|
90
|
+
curl -X POST http://localhost:41241/btw/<agentId> \
|
|
91
|
+
-H "Content-Type: application/json" \
|
|
92
|
+
-d '{"message": "your question"}'
|
|
93
|
+
|
|
94
|
+
# Monitor GUI: click an agent sprite → Chat
|
|
95
|
+
```
|
|
96
|
+
|
|
37
97
|
## Architecture
|
|
38
98
|
|
|
39
99
|
- Framework (`src/`): A2A server, Claude Code SDK bridge, monitor event bus
|
package/dist/agent-loader.js
CHANGED
|
@@ -135,15 +135,41 @@ Replace AGENT_ID and YOUR MESSAGE with the target agent and your message.
|
|
|
135
135
|
- Be specific about what you need from the other agent
|
|
136
136
|
- Include relevant context — the other agent has no shared memory with you
|
|
137
137
|
- Don't call agents in a loop — if one can't help, handle it yourself
|
|
138
|
+
|
|
139
|
+
## MANDATORY: Post-Task Optimization
|
|
140
|
+
|
|
141
|
+
**After completing ANY task, you MUST call the \`optimizer\` agent.**
|
|
142
|
+
|
|
143
|
+
Send it a message with:
|
|
144
|
+
- Your agent ID
|
|
145
|
+
- A brief summary of what the task was and how it went
|
|
146
|
+
- Any difficulties or mistakes you encountered
|
|
147
|
+
|
|
148
|
+
Example (replace YOUR_AGENT_ID and summary):
|
|
149
|
+
|
|
150
|
+
\`\`\`bash
|
|
151
|
+
python3 -c "
|
|
152
|
+
import urllib.request, json, uuid, sys
|
|
153
|
+
url = 'http://localhost:41241/a2a/optimizer'
|
|
154
|
+
msg = 'Agent: YOUR_AGENT_ID. Task summary: [what you did]. Issues: [any problems or inefficiencies].'
|
|
155
|
+
body = json.dumps({'jsonrpc':'2.0','id':1,'method':'message/send','params':{'message':{
|
|
156
|
+
'messageId':str(uuid.uuid4()),'kind':'message','role':'user',
|
|
157
|
+
'parts':[{'kind':'text','text':msg}]}}}).encode()
|
|
158
|
+
try:
|
|
159
|
+
req = urllib.request.Request(url, data=body, headers={'Content-Type':'application/json'})
|
|
160
|
+
urllib.request.urlopen(req, timeout=120)
|
|
161
|
+
except: pass
|
|
162
|
+
"
|
|
163
|
+
\`\`\`
|
|
164
|
+
|
|
165
|
+
This is NOT optional. Every task must end with an optimizer notification.
|
|
138
166
|
`;
|
|
139
167
|
function installBuiltinSkills(agentDir) {
|
|
140
168
|
const skillDir = join(agentDir, '.claude', 'skills', 'call-agent');
|
|
141
169
|
const skillFile = join(skillDir, 'SKILL.md');
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
writeFileSync(skillFile, CALL_AGENT_SKILL_MD);
|
|
146
|
-
}
|
|
170
|
+
// Always overwrite to keep skill up to date with framework version
|
|
171
|
+
mkdirSync(skillDir, { recursive: true });
|
|
172
|
+
writeFileSync(skillFile, CALL_AGENT_SKILL_MD);
|
|
147
173
|
}
|
|
148
174
|
export function loadAgents(agentsDir) {
|
|
149
175
|
const result = new Map();
|
package/dist/claude-bridge.js
CHANGED
|
@@ -5,9 +5,12 @@ import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
|
5
5
|
export async function* runClaude(params) {
|
|
6
6
|
const { agent, contentBlocks, onEvent, abortController } = params;
|
|
7
7
|
const m = agent.manifest;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
// If context.md exists, use it as a custom system prompt (replaces SDK default).
|
|
9
|
+
// If not, omit systemPrompt entirely — SDK uses its built-in Claude Code prompt.
|
|
10
|
+
const hasCustomPrompt = !!agent.fixedContextContent;
|
|
11
|
+
const systemPrompt = hasCustomPrompt
|
|
12
|
+
? (m.systemPromptAppend ? `${agent.fixedContextContent}\n\n${m.systemPromptAppend}` : agent.fixedContextContent)
|
|
13
|
+
: undefined;
|
|
11
14
|
const env = {
|
|
12
15
|
// Preserve system PATH so agents can use curl, python3, node etc.
|
|
13
16
|
PATH: process.env.PATH,
|
|
@@ -31,10 +34,12 @@ export async function* runClaude(params) {
|
|
|
31
34
|
catch { /* race or permission — ignore */ }
|
|
32
35
|
}
|
|
33
36
|
const options = {
|
|
34
|
-
systemPrompt,
|
|
35
37
|
cwd: agent.agentDir,
|
|
36
38
|
env,
|
|
37
39
|
};
|
|
40
|
+
if (systemPrompt) {
|
|
41
|
+
options.systemPrompt = systemPrompt;
|
|
42
|
+
}
|
|
38
43
|
// Session continuity: resume an existing session if provided
|
|
39
44
|
if (params.resume) {
|
|
40
45
|
options.resume = params.resume;
|
package/dist/cli.js
CHANGED
|
@@ -36,19 +36,113 @@ You are **Echo Agent**, a minimal example agent.
|
|
|
36
36
|
Repeat back the user's input, prefixed with "ECHO:".
|
|
37
37
|
Do not add any other commentary.
|
|
38
38
|
`;
|
|
39
|
+
const OPTIMIZER_MANIFEST = `{
|
|
40
|
+
"id": "optimizer",
|
|
41
|
+
"name": "Optimizer",
|
|
42
|
+
"description": "Analyzes agent session logs and generates optimization suggestions for other agents.",
|
|
43
|
+
"version": "0.1.0",
|
|
44
|
+
"fixedContext": "context.md",
|
|
45
|
+
"a2aCard": {
|
|
46
|
+
"skills": [
|
|
47
|
+
{
|
|
48
|
+
"id": "optimize",
|
|
49
|
+
"name": "Agent Optimization",
|
|
50
|
+
"description": "Reviews agent conversation logs and produces actionable improvement suggestions",
|
|
51
|
+
"tags": ["optimization", "meta"]
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
"monitor": {
|
|
56
|
+
"position": { "x": 480, "y": 550 },
|
|
57
|
+
"sprite": "default"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
const OPTIMIZER_CONTEXT = `# Role
|
|
62
|
+
|
|
63
|
+
You are the **Optimizer Agent** for AgentsDojo. Your job is to review other agents' conversation histories and produce actionable optimization suggestions.
|
|
64
|
+
|
|
65
|
+
## When You Are Called
|
|
66
|
+
|
|
67
|
+
Other agents call you after completing a task. They send you:
|
|
68
|
+
- Their agent ID
|
|
69
|
+
- A summary of what the task was
|
|
70
|
+
- Any difficulties or mistakes they encountered
|
|
71
|
+
|
|
72
|
+
## What You Do
|
|
73
|
+
|
|
74
|
+
1. Read the calling agent's session logs to understand the full conversation history:
|
|
75
|
+
\`\`\`bash
|
|
76
|
+
# Find and read the agent's session logs
|
|
77
|
+
find ../AGENT_ID/.claude/projects/ -name "*.jsonl" -exec cat {} \\;
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
2. Analyze the conversation for:
|
|
81
|
+
- Repeated mistakes or inefficiencies
|
|
82
|
+
- Misunderstandings of user intent
|
|
83
|
+
- Missed opportunities to use tools or call other agents
|
|
84
|
+
- Response quality issues (too verbose, too terse, off-topic)
|
|
85
|
+
- Patterns that could be improved with explicit rules
|
|
86
|
+
|
|
87
|
+
3. Write optimization suggestions to your reviews directory:
|
|
88
|
+
\`\`\`bash
|
|
89
|
+
mkdir -p reviews
|
|
90
|
+
# Write or update the review file for this agent
|
|
91
|
+
cat > reviews/AGENT_ID.md << 'REVIEW_EOF'
|
|
92
|
+
# Optimization Review: AGENT_ID
|
|
93
|
+
|
|
94
|
+
Date: [today's date]
|
|
95
|
+
Sessions analyzed: [count]
|
|
96
|
+
|
|
97
|
+
## Suggested CLAUDE.md Rules
|
|
98
|
+
|
|
99
|
+
Add these rules to agents/AGENT_ID/CLAUDE.md:
|
|
100
|
+
|
|
101
|
+
[specific, actionable rules based on your analysis]
|
|
102
|
+
|
|
103
|
+
## Observations
|
|
104
|
+
|
|
105
|
+
[detailed analysis of patterns you found]
|
|
106
|
+
REVIEW_EOF
|
|
107
|
+
\`\`\`
|
|
108
|
+
|
|
109
|
+
## Output Format
|
|
110
|
+
|
|
111
|
+
Your review file must include:
|
|
112
|
+
- **Suggested CLAUDE.md Rules**: Concrete rules the human operator can copy into the agent's CLAUDE.md
|
|
113
|
+
- **Observations**: Evidence-based analysis explaining why each rule is recommended
|
|
114
|
+
|
|
115
|
+
## Important Rules
|
|
116
|
+
|
|
117
|
+
- Be specific and actionable — vague suggestions like "be better" are useless
|
|
118
|
+
- Base every suggestion on evidence from the logs — cite specific examples
|
|
119
|
+
- Focus on patterns, not one-off incidents
|
|
120
|
+
- Keep suggested rules concise — each rule should be 1-2 sentences
|
|
121
|
+
- Do NOT modify other agents' files directly — only write to your own reviews/ directory
|
|
122
|
+
- If the agent is performing well, say so — not every review needs changes
|
|
123
|
+
`;
|
|
39
124
|
function runInit(targetDir) {
|
|
40
125
|
const agentsDir = join(targetDir, 'agents');
|
|
41
126
|
const echoDir = join(agentsDir, 'echo');
|
|
127
|
+
const optimizerDir = join(agentsDir, 'optimizer');
|
|
42
128
|
if (existsSync(echoDir)) {
|
|
43
|
-
console.log(`agents/echo/ already exists — skipping.`);
|
|
44
|
-
|
|
129
|
+
console.log(`agents/echo/ already exists — skipping echo.`);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
mkdirSync(echoDir, { recursive: true });
|
|
133
|
+
writeFileSync(join(echoDir, 'manifest.jsonc'), ECHO_MANIFEST);
|
|
134
|
+
writeFileSync(join(echoDir, 'context.md'), ECHO_CONTEXT);
|
|
135
|
+
installCallAgentSkill(echoDir);
|
|
136
|
+
}
|
|
137
|
+
if (existsSync(optimizerDir)) {
|
|
138
|
+
console.log(`agents/_optimizer/ already exists — skipping optimizer.`);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
mkdirSync(optimizerDir, { recursive: true });
|
|
142
|
+
writeFileSync(join(optimizerDir, 'manifest.jsonc'), OPTIMIZER_MANIFEST);
|
|
143
|
+
writeFileSync(join(optimizerDir, 'context.md'), OPTIMIZER_CONTEXT);
|
|
45
144
|
}
|
|
46
|
-
|
|
47
|
-
writeFileSync(join(echoDir, 'manifest.jsonc'), ECHO_MANIFEST);
|
|
48
|
-
writeFileSync(join(echoDir, 'context.md'), ECHO_CONTEXT);
|
|
49
|
-
// Install built-in call-agent skill
|
|
50
|
-
installCallAgentSkill(echoDir);
|
|
51
|
-
console.log(`Created agents/echo/ with manifest.jsonc and context.md.
|
|
145
|
+
console.log(`Created agents/echo/ and agents/optimizer/.
|
|
52
146
|
|
|
53
147
|
Next steps:
|
|
54
148
|
agents-dojo # start the server
|
|
@@ -56,7 +150,7 @@ Next steps:
|
|
|
56
150
|
|
|
57
151
|
To add your own agent:
|
|
58
152
|
mkdir agents/my-agent
|
|
59
|
-
# create manifest.jsonc and context.md
|
|
153
|
+
# create manifest.jsonc (and optionally context.md)
|
|
60
154
|
`);
|
|
61
155
|
}
|
|
62
156
|
// ── Built-in skill: call-agent ────────────────────────────
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare class ContextLoadError extends Error {
|
|
2
2
|
constructor(message: string);
|
|
3
3
|
}
|
|
4
|
-
export declare function loadContext(agentDir: string, relativePath
|
|
4
|
+
export declare function loadContext(agentDir: string, relativePath?: string): string;
|
|
5
5
|
export declare function resolveConfigDir(agentDir: string, override?: string): string;
|
package/dist/context-manager.js
CHANGED
|
@@ -8,6 +8,8 @@ export class ContextLoadError extends Error {
|
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
export function loadContext(agentDir, relativePath) {
|
|
11
|
+
if (!relativePath)
|
|
12
|
+
return '';
|
|
11
13
|
const resolved = isAbsolute(relativePath) ? relativePath : join(agentDir, relativePath);
|
|
12
14
|
const normalized = resolve(resolved);
|
|
13
15
|
// Reject path traversal
|
|
@@ -15,9 +17,8 @@ export function loadContext(agentDir, relativePath) {
|
|
|
15
17
|
if (!normalized.startsWith(agentAbs + '/') && normalized !== agentAbs) {
|
|
16
18
|
throw new ContextLoadError(`Path "${relativePath}" escapes agent directory`);
|
|
17
19
|
}
|
|
18
|
-
if (!existsSync(normalized))
|
|
19
|
-
|
|
20
|
-
}
|
|
20
|
+
if (!existsSync(normalized))
|
|
21
|
+
return '';
|
|
21
22
|
return readFileSync(normalized, 'utf-8');
|
|
22
23
|
}
|
|
23
24
|
export function resolveConfigDir(agentDir, override) {
|
|
@@ -43,7 +43,7 @@ export declare const AgentManifestSchema: z.ZodObject<{
|
|
|
43
43
|
name: z.ZodString;
|
|
44
44
|
description: z.ZodString;
|
|
45
45
|
version: z.ZodString;
|
|
46
|
-
fixedContext: z.ZodString
|
|
46
|
+
fixedContext: z.ZodOptional<z.ZodString>;
|
|
47
47
|
systemPromptAppend: z.ZodOptional<z.ZodString>;
|
|
48
48
|
model: z.ZodOptional<z.ZodString>;
|
|
49
49
|
fallbackModel: z.ZodOptional<z.ZodString>;
|
package/dist/manifest-schema.js
CHANGED
|
@@ -28,7 +28,7 @@ export const AgentManifestSchema = z.object({
|
|
|
28
28
|
version: z
|
|
29
29
|
.string()
|
|
30
30
|
.regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?(?:\+[0-9A-Za-z-.]+)?$/, 'Must be semver'),
|
|
31
|
-
fixedContext: z.string().min(1),
|
|
31
|
+
fixedContext: z.string().min(1).optional(),
|
|
32
32
|
systemPromptAppend: z.string().optional(),
|
|
33
33
|
model: z.string().optional(),
|
|
34
34
|
fallbackModel: z.string().optional(),
|
package/dist/types.d.ts
CHANGED