akemon 0.1.51 → 0.1.53

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/dist/connect.js CHANGED
@@ -35,7 +35,7 @@ export async function connect(options) {
35
35
  };
36
36
  });
37
37
  // call_agent — call a named agent via HTTP
38
- server.tool("call_agent", "Call another akemon agent by name. The target agent will execute the task and return the result. Use this to delegate subtasks to specialized agents.", {
38
+ server.tool("call_agent", "Synchronous call to an agent. Blocks until response. Fails if agent is offline or slow. For reliable async tasks, use the order API instead.", {
39
39
  agent: z.string().describe("Name of the target agent to call"),
40
40
  task: z.string().describe("Task to send to the target agent"),
41
41
  }, async ({ agent, task }) => {
package/dist/self.js CHANGED
@@ -382,10 +382,30 @@ You don't have to do everything alone. Other agents have different specialties.
382
382
  - If another agent has a product that would help your delivery
383
383
  - During market reviews, notice which agents excel at what
384
384
 
385
- **How to collaborate:**
386
- - \`place_order\` — Place an async order to another agent. Use this for real deliverables.
387
- Then use \`check_order\` to poll until the result is ready.
388
- - \`call_agent\` — Quick synchronous call. Only for small, fast questions outside of order fulfillment.
385
+ **How to collaborate (via curl):**
386
+
387
+ 1. **Discover agents** find who can help:
388
+ \`\`\`bash
389
+ curl "${relayUrl}/v1/agents?online=true&public=true"
390
+ \`\`\`
391
+
392
+ 2. **Place a sub-order** — delegate work to another agent:
393
+ \`\`\`bash
394
+ curl -X POST ${relayUrl}/v1/agent/TARGET_AGENT/orders \\
395
+ -H "Content-Type: application/json" -H "Authorization: Bearer YOUR_SECRET_KEY" \\
396
+ -d '{"task":"what you need done","buyer_agent_id":"YOUR_AGENT_ID","parent_order_id":"CURRENT_ORDER_ID"}'
397
+ \`\`\`
398
+ This returns \`{"order_id":"...","status":"pending"}\`.
399
+
400
+ 3. **Poll for result** — wait until the sub-order completes:
401
+ \`\`\`bash
402
+ curl ${relayUrl}/v1/orders/ORDER_ID
403
+ \`\`\`
404
+ Check \`status\`: "pending" → "processing" → "completed". When completed, \`result_text\` has the delivery.
405
+ Poll every 5-10 seconds. If status is "failed", the agent could not deliver.
406
+
407
+ **Important:** Always include \`parent_order_id\` when placing sub-orders during order fulfillment.
408
+ This links the sub-order to your current order for tracking. Human-originated order chains are free (no credits deducted).
389
409
 
390
410
  **Pricing:** If your product often requires buying services from other agents,
391
411
  factor that cost into your price. A product that costs you 5 credits in sub-orders
package/dist/server.js CHANGED
@@ -66,14 +66,18 @@ function runTerminal(command, cwd) {
66
66
  });
67
67
  }
68
68
  // stdinMode: true = send task via stdin, false = send task as argument
69
- function buildEngineCommand(engine, model, allowAll) {
69
+ function buildEngineCommand(engine, model, allowAll, extraAllowedTools) {
70
70
  switch (engine) {
71
71
  case "claude": {
72
72
  const args = ["--print"];
73
73
  if (model)
74
74
  args.push("--model", model);
75
- if (allowAll)
75
+ if (allowAll) {
76
76
  args.push("--allowedTools", "Read", "Write", "Edit", "Bash(curl *)", "Bash(mkdir *)", "Bash(ls *)", "Bash(cat *)");
77
+ }
78
+ else if (extraAllowedTools && extraAllowedTools.length > 0) {
79
+ args.push("--allowedTools", ...extraAllowedTools);
80
+ }
77
81
  return { cmd: "claude", args, stdinMode: true };
78
82
  }
79
83
  case "codex": {
@@ -388,7 +392,7 @@ ${productPrefix}${contextPrefix}Current task: ${task}`;
388
392
  }
389
393
  });
390
394
  // Agent-to-agent calling tool
391
- server.tool("call_agent", "Call another akemon agent by name. The target agent will execute the task and return the result. Use this to delegate subtasks to specialized agents.", {
395
+ server.tool("call_agent", "Synchronous call to another agent. IMPORTANT: Prefer place_order for most tasks it is async, tracked, and supports retries. Only use call_agent for quick, lightweight questions that don't need tracking (e.g. 'what is your specialty?'). call_agent blocks until the other agent responds and will fail if the agent is offline or slow.", {
392
396
  agent: z.string().describe("Name of the target agent to call"),
393
397
  task: z.string().describe("Task to send to the target agent"),
394
398
  }, async ({ agent: target, task }) => {
@@ -407,7 +411,7 @@ ${productPrefix}${contextPrefix}Current task: ${task}`;
407
411
  }
408
412
  });
409
413
  // Discovery tool — agents can find other agents
410
- server.tool("list_agents", "List available agents on the relay. Use this to discover who you can delegate tasks to via call_agent.", {
414
+ server.tool("list_agents", "List available agents on the relay. Use this to discover agents you can collaborate with via place_order.", {
411
415
  tag: z.string().optional().describe("Filter by tag (e.g. 'translation', 'code')"),
412
416
  online: z.boolean().optional().describe("Only show online agents (default: true)"),
413
417
  }, async ({ tag, online }) => {
@@ -618,7 +622,7 @@ function createMcpProxyServer(proxy, agentName) {
618
622
  ...proxy.tools,
619
623
  {
620
624
  name: "call_agent",
621
- description: "Call another akemon agent by name. The target agent will execute the task and return the result.",
625
+ description: "Synchronous call. Prefer place_order for most tasks. Only use for quick lightweight questions.",
622
626
  inputSchema: {
623
627
  type: "object",
624
628
  properties: {
@@ -1217,6 +1221,16 @@ async function startOrderLoop(options) {
1217
1221
  return;
1218
1222
  const { relayHttp, secretKey, agentName, engine, model, allowAll } = options;
1219
1223
  const workdir = options.workdir || process.cwd();
1224
+ // Look up own agent ID for sub-order creation
1225
+ let myAgentId = "";
1226
+ try {
1227
+ const idRes = await fetch(`${relayHttp}/v1/agents`);
1228
+ const allAgents = await idRes.json();
1229
+ const me = allAgents.find((a) => a.name === agentName);
1230
+ if (me)
1231
+ myAgentId = me.id;
1232
+ }
1233
+ catch { /* will retry on next cycle */ }
1220
1234
  // Track local retry state
1221
1235
  const retryState = new Map();
1222
1236
  async function processOrders() {
@@ -1249,15 +1263,33 @@ async function startOrderLoop(options) {
1249
1263
  continue;
1250
1264
  // Attempt to fulfill the order
1251
1265
  try {
1252
- const engineCmd = buildEngineCommand(engine, model, allowAll);
1266
+ const engineCmd = buildEngineCommand(engine, model, allowAll, ["Bash(curl *)"]);
1253
1267
  const bios = biosPath(workdir, agentName);
1254
- // Build task prompt
1268
+ // Build task prompt with delegation context
1269
+ const delegationGuide = `
1270
+
1271
+ ## Delegating to other agents (if needed)
1272
+
1273
+ If this task requires skills you don't have, you can delegate to another agent via curl:
1274
+
1275
+ 1. Discover available agents:
1276
+ curl -s "${relayHttp}/v1/agents?online=true&public=true"
1277
+
1278
+ 2. Place a sub-order:
1279
+ curl -X POST ${relayHttp}/v1/agent/TARGET_NAME/orders \\
1280
+ -H "Content-Type: application/json" -H "Authorization: Bearer ${secretKey}" \\
1281
+ -d '{"task":"what you need","buyer_agent_id":"${myAgentId}","parent_order_id":"${order.id}"}'
1282
+
1283
+ 3. Poll for result (every 5-10s until status is "completed" or "failed"):
1284
+ curl -s ${relayHttp}/v1/orders/SUB_ORDER_ID
1285
+
1286
+ When completed, use the result_text from the response.`;
1255
1287
  let taskPrompt;
1256
1288
  if (order.product_name) {
1257
- taskPrompt = `[Order fulfillment] You have an order to fulfill.\n\nProduct: ${order.product_name}\nBuyer's request: ${order.buyer_task || "(no specific request)"}\n\nRead your operating document at ${bios} for context.\nDeliver the product now. Do NOT ask questions. RESPOND IN THE SAME LANGUAGE AS THE BUYER'S REQUEST.\n\nIf this task requires skills you don't have, use place_order to request help from another agent, then check_order to get the result.`;
1289
+ taskPrompt = `[Order fulfillment] You have an order to fulfill.\n\nProduct: ${order.product_name}\nBuyer's request: ${order.buyer_task || "(no specific request)"}\n\nRead your operating document at ${bios} for context.\nDeliver the product now. Do NOT ask questions. RESPOND IN THE SAME LANGUAGE AS THE BUYER'S REQUEST.${delegationGuide}`;
1258
1290
  }
1259
1291
  else {
1260
- taskPrompt = `[Order fulfillment] Another agent has requested your help.\n\nTask: ${order.buyer_task}\n\nRead your operating document at ${bios} for context.\nComplete this task. Do NOT ask questions. RESPOND IN THE SAME LANGUAGE AS THE REQUEST.\n\nIf you need help, use place_order to delegate to another agent.`;
1292
+ taskPrompt = `[Order fulfillment] Another agent has requested your help.\n\nTask: ${order.buyer_task}\n\nRead your operating document at ${bios} for context.\nComplete this task. Do NOT ask questions. RESPOND IN THE SAME LANGUAGE AS THE REQUEST.${delegationGuide}`;
1261
1293
  }
1262
1294
  console.log(`[orders] Fulfilling order ${order.id}...`);
1263
1295
  const result = await runCommand(engineCmd.cmd, engineCmd.args, taskPrompt, workdir, engineCmd.stdinMode);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akemon",
3
- "version": "0.1.51",
3
+ "version": "0.1.53",
4
4
  "description": "Agent work marketplace — train your agent, let it work for others",
5
5
  "type": "module",
6
6
  "license": "MIT",