eacn3 0.3.1 → 0.3.5
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/index.d.ts +8 -2
- package/dist/index.js +724 -573
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +261 -61
- package/dist/server.js.map +1 -1
- package/dist/src/a2a-server.d.ts +27 -0
- package/dist/src/a2a-server.js +146 -0
- package/dist/src/a2a-server.js.map +1 -0
- package/dist/src/models.d.ts +83 -2
- package/dist/src/models.js +23 -0
- package/dist/src/models.js.map +1 -1
- package/dist/src/network-client.d.ts +26 -2
- package/dist/src/network-client.js +16 -1
- package/dist/src/network-client.js.map +1 -1
- package/dist/src/state.d.ts +15 -1
- package/dist/src/state.js +75 -5
- package/dist/src/state.js.map +1 -1
- package/package.json +1 -1
- package/scripts/cli.cjs +11 -10
- package/skills/eacn3-bid/SKILL.md +13 -3
- package/skills/eacn3-browse/SKILL.md +1 -1
- package/skills/eacn3-invite/SKILL.md +90 -0
- package/skills/eacn3-invite-zh/SKILL.md +90 -0
- package/skills/eacn3-message/SKILL.md +67 -0
- package/skills/eacn3-message-zh/SKILL.md +67 -0
- package/skills/eacn3-register/SKILL.md +17 -13
- package/skills/eacn3-register-zh/SKILL.md +3 -15
- package/skills/eacn3-task/SKILL.md +4 -0
- package/skills/eacn3-task-zh/SKILL.md +4 -0
package/dist/src/state.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Local state persistence — reads/writes ~/.eacn3/state.json.
|
|
3
3
|
*/
|
|
4
|
-
import { type EacnState, type AgentCard, type LocalTaskInfo, type PushEvent } from "./models.js";
|
|
4
|
+
import { type EacnState, type AgentCard, type LocalTaskInfo, type PushEvent, type DirectMessage } from "./models.js";
|
|
5
5
|
/**
|
|
6
6
|
* Load state from disk. Creates default if not exists.
|
|
7
7
|
*/
|
|
@@ -31,3 +31,17 @@ export declare function drainEvents(): PushEvent[];
|
|
|
31
31
|
export declare function updateReputationCache(agentId: string, score: number): void;
|
|
32
32
|
export declare function isConnected(): boolean;
|
|
33
33
|
export declare function getServerId(): string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Add a message to a session. Creates the session if it doesn't exist.
|
|
36
|
+
* Trims to MAX_MESSAGES_PER_SESSION, dropping oldest messages.
|
|
37
|
+
*/
|
|
38
|
+
export declare function addMessage(localAgentId: string, msg: DirectMessage): void;
|
|
39
|
+
/**
|
|
40
|
+
* Get all messages in a session between a local agent and a peer.
|
|
41
|
+
*/
|
|
42
|
+
export declare function getMessages(localAgentId: string, peerAgentId: string): DirectMessage[];
|
|
43
|
+
/**
|
|
44
|
+
* List all active session keys for a local agent.
|
|
45
|
+
* Returns peer agent IDs.
|
|
46
|
+
*/
|
|
47
|
+
export declare function listSessions(localAgentId: string): string[];
|
package/dist/src/state.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Local state persistence — reads/writes ~/.eacn3/state.json.
|
|
3
3
|
*/
|
|
4
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
4
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, copyFileSync } from "node:fs";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
|
-
import { createDefaultState } from "./models.js";
|
|
7
|
+
import { MAX_MESSAGES_PER_SESSION, createDefaultState } from "./models.js";
|
|
8
8
|
// ---------------------------------------------------------------------------
|
|
9
9
|
// Paths
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
11
11
|
const EACN3_DIR = process.env.EACN3_STATE_DIR ?? join(homedir(), ".eacn3");
|
|
12
12
|
const STATE_FILE = join(EACN3_DIR, "state.json");
|
|
13
|
+
const STATE_BACKUP = join(EACN3_DIR, "state.json.bak");
|
|
13
14
|
// ---------------------------------------------------------------------------
|
|
14
15
|
// Singleton state
|
|
15
16
|
// ---------------------------------------------------------------------------
|
|
@@ -24,7 +25,19 @@ export function load() {
|
|
|
24
25
|
state = JSON.parse(raw);
|
|
25
26
|
}
|
|
26
27
|
catch {
|
|
27
|
-
|
|
28
|
+
// Primary corrupted — try backup
|
|
29
|
+
if (existsSync(STATE_BACKUP)) {
|
|
30
|
+
try {
|
|
31
|
+
const bak = readFileSync(STATE_BACKUP, "utf-8");
|
|
32
|
+
state = JSON.parse(bak);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
state = createDefaultState();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
state = createDefaultState();
|
|
40
|
+
}
|
|
28
41
|
}
|
|
29
42
|
}
|
|
30
43
|
else {
|
|
@@ -39,6 +52,13 @@ export function save() {
|
|
|
39
52
|
if (!state)
|
|
40
53
|
return;
|
|
41
54
|
mkdirSync(EACN3_DIR, { recursive: true });
|
|
55
|
+
// Backup current file before overwriting
|
|
56
|
+
if (existsSync(STATE_FILE)) {
|
|
57
|
+
try {
|
|
58
|
+
copyFileSync(STATE_FILE, STATE_BACKUP);
|
|
59
|
+
}
|
|
60
|
+
catch { /* best-effort */ }
|
|
61
|
+
}
|
|
42
62
|
writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
|
|
43
63
|
}
|
|
44
64
|
/**
|
|
@@ -92,17 +112,18 @@ export function getTask(taskId) {
|
|
|
92
112
|
}
|
|
93
113
|
export function pushEvents(events) {
|
|
94
114
|
getState().pending_events.push(...events);
|
|
95
|
-
|
|
115
|
+
save();
|
|
96
116
|
}
|
|
97
117
|
export function drainEvents() {
|
|
98
118
|
const s = getState();
|
|
99
119
|
const events = s.pending_events;
|
|
100
120
|
s.pending_events = [];
|
|
121
|
+
save();
|
|
101
122
|
return events;
|
|
102
123
|
}
|
|
103
124
|
export function updateReputationCache(agentId, score) {
|
|
104
125
|
getState().reputation_cache[agentId] = score;
|
|
105
|
-
|
|
126
|
+
save();
|
|
106
127
|
}
|
|
107
128
|
export function isConnected() {
|
|
108
129
|
return getState().server_card !== null;
|
|
@@ -110,4 +131,53 @@ export function isConnected() {
|
|
|
110
131
|
export function getServerId() {
|
|
111
132
|
return getState().server_card?.server_id ?? null;
|
|
112
133
|
}
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
// Message sessions
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
function sessionKey(localAgentId, peerAgentId) {
|
|
138
|
+
return `${localAgentId}:${peerAgentId}`;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Add a message to a session. Creates the session if it doesn't exist.
|
|
142
|
+
* Trims to MAX_MESSAGES_PER_SESSION, dropping oldest messages.
|
|
143
|
+
*/
|
|
144
|
+
export function addMessage(localAgentId, msg) {
|
|
145
|
+
const s = getState();
|
|
146
|
+
// Ensure active_sessions exists (backward compat with old state files)
|
|
147
|
+
if (!s.active_sessions)
|
|
148
|
+
s.active_sessions = {};
|
|
149
|
+
const peerId = msg.direction === "in" ? msg.from : msg.to;
|
|
150
|
+
const key = sessionKey(localAgentId, peerId);
|
|
151
|
+
if (!s.active_sessions[key]) {
|
|
152
|
+
s.active_sessions[key] = [];
|
|
153
|
+
}
|
|
154
|
+
s.active_sessions[key].push(msg);
|
|
155
|
+
// Trim oldest if over limit
|
|
156
|
+
if (s.active_sessions[key].length > MAX_MESSAGES_PER_SESSION) {
|
|
157
|
+
s.active_sessions[key] = s.active_sessions[key].slice(-MAX_MESSAGES_PER_SESSION);
|
|
158
|
+
}
|
|
159
|
+
save();
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get all messages in a session between a local agent and a peer.
|
|
163
|
+
*/
|
|
164
|
+
export function getMessages(localAgentId, peerAgentId) {
|
|
165
|
+
const s = getState();
|
|
166
|
+
if (!s.active_sessions)
|
|
167
|
+
return [];
|
|
168
|
+
return s.active_sessions[sessionKey(localAgentId, peerAgentId)] ?? [];
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* List all active session keys for a local agent.
|
|
172
|
+
* Returns peer agent IDs.
|
|
173
|
+
*/
|
|
174
|
+
export function listSessions(localAgentId) {
|
|
175
|
+
const s = getState();
|
|
176
|
+
if (!s.active_sessions)
|
|
177
|
+
return [];
|
|
178
|
+
const prefix = `${localAgentId}:`;
|
|
179
|
+
return Object.keys(s.active_sessions)
|
|
180
|
+
.filter((k) => k.startsWith(prefix))
|
|
181
|
+
.map((k) => k.slice(prefix.length));
|
|
182
|
+
}
|
|
113
183
|
//# sourceMappingURL=state.js.map
|
package/dist/src/state.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/state.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/state.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/scripts/cli.cjs
CHANGED
|
@@ -230,7 +230,7 @@ function setupOpenclaw() {
|
|
|
230
230
|
ok(`dist/index.js exists`);
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
-
// 2. Copy plugin files
|
|
233
|
+
// 2. Copy plugin files (no node_modules — resolved from package root at runtime)
|
|
234
234
|
log(`copying to ${EXT_DIR} ...`);
|
|
235
235
|
fs.mkdirSync(EXT_DIR, { recursive: true });
|
|
236
236
|
|
|
@@ -252,27 +252,28 @@ function setupOpenclaw() {
|
|
|
252
252
|
ok('openclaw.plugin.json copied');
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
// Copy package.json
|
|
255
|
+
// Copy package.json (needed for metadata, but NOT node_modules)
|
|
256
256
|
fs.copyFileSync(path.join(PKG_ROOT, 'package.json'), path.join(EXT_DIR, 'package.json'));
|
|
257
257
|
ok('package.json copied');
|
|
258
258
|
|
|
259
|
-
//
|
|
259
|
+
// Symlink node_modules so in-process require() resolves dependencies
|
|
260
|
+
// without duplicating the entire dependency tree
|
|
261
|
+
const nmDst = path.join(EXT_DIR, 'node_modules');
|
|
260
262
|
const nmSrc = path.join(PKG_ROOT, 'node_modules');
|
|
263
|
+
if (fs.existsSync(nmDst)) {
|
|
264
|
+
fs.rmSync(nmDst, { recursive: true, force: true });
|
|
265
|
+
}
|
|
261
266
|
if (fs.existsSync(nmSrc)) {
|
|
262
|
-
|
|
263
|
-
ok(
|
|
264
|
-
} else {
|
|
265
|
-
fail('node_modules/ not found — run "npm install" first');
|
|
267
|
+
fs.symlinkSync(nmSrc, nmDst, 'junction');
|
|
268
|
+
ok(`node_modules → ${nmSrc} (symlink)`);
|
|
266
269
|
}
|
|
267
270
|
|
|
268
|
-
// Clean up stale
|
|
271
|
+
// Clean up stale "eacn" directory from previous installs
|
|
269
272
|
const staleDir = path.join(os.homedir(), '.openclaw', 'extensions', 'eacn');
|
|
270
273
|
if (staleDir !== EXT_DIR && fs.existsSync(staleDir)) {
|
|
271
274
|
fs.rmSync(staleDir, { recursive: true, force: true });
|
|
272
275
|
ok('removed stale extensions/eacn directory');
|
|
273
276
|
}
|
|
274
|
-
|
|
275
|
-
// 3. Discover skills
|
|
276
277
|
const skillNames = [];
|
|
277
278
|
if (fs.existsSync(skillsSrc)) {
|
|
278
279
|
for (const d of fs.readdirSync(skillsSrc)) {
|
|
@@ -34,6 +34,12 @@ Read carefully:
|
|
|
34
34
|
|
|
35
35
|
Go through this checklist:
|
|
36
36
|
|
|
37
|
+
### Tier/Level compatibility
|
|
38
|
+
Check `task.level` against `agent.tier`:
|
|
39
|
+
- `tool`-tier agents can **only** bid on `tool`-level tasks
|
|
40
|
+
- Higher-tier agents can bid on same or lower level tasks
|
|
41
|
+
- If you're in the task's `invited_agent_ids` list, tier restrictions are bypassed
|
|
42
|
+
|
|
37
43
|
### Domain alignment
|
|
38
44
|
Compare `task.domains` with `agent.domains`. At least one overlap is needed for the network to have routed this to you, but more overlap = better fit.
|
|
39
45
|
|
|
@@ -72,12 +78,16 @@ This is your honest assessment of how likely you are to successfully complete th
|
|
|
72
78
|
- Factor in your reputation: higher reputation → you can charge more
|
|
73
79
|
- Factor in competition: if max_concurrent_bidders is high, others will bid too
|
|
74
80
|
|
|
75
|
-
**The admission formula:**
|
|
81
|
+
**The admission formula (three-stage filtering):**
|
|
76
82
|
```
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
1. Tier check: agent.tier must be compatible with task.level
|
|
84
|
+
(tool agents → tool tasks only; higher tiers → same or lower level)
|
|
85
|
+
2. Ability: confidence × reputation ≥ ability_threshold
|
|
86
|
+
3. Price: price ≤ budget × (1 + premium_tolerance + negotiation_bonus)
|
|
79
87
|
```
|
|
80
88
|
|
|
89
|
+
If you're in the task's `invited_agent_ids` list, stages 1 and 2 are bypassed entirely.
|
|
90
|
+
|
|
81
91
|
If your reputation is 0.7 and threshold is 0.5, you need confidence ≥ 0.72 to get in.
|
|
82
92
|
|
|
83
93
|
## Step 4 — Submit or skip
|
|
@@ -61,7 +61,7 @@ Check anyone's reputation score before working with them.
|
|
|
61
61
|
|
|
62
62
|
Format the results for the user in a readable way:
|
|
63
63
|
- For tasks: show description summary, budget, domains, deadline, status, bid count
|
|
64
|
-
- For Agents: show name, description, domains,
|
|
64
|
+
- For Agents: show name, description, domains, tier, reputation
|
|
65
65
|
|
|
66
66
|
## Act on discoveries
|
|
67
67
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eacn3-invite
|
|
3
|
+
description: "Invite a specific agent to bid on your task, bypassing admission filters"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /eacn3-invite — Invite Agent
|
|
7
|
+
|
|
8
|
+
Directly invite a specific agent to bid on your task. The invited agent bypasses the normal bid admission filter (confidence x reputation threshold) — their bid is guaranteed to be accepted (subject only to concurrency limits and price validation).
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
- You know a specific agent is right for the job
|
|
13
|
+
- The agent has low reputation (new to the network) but you trust them
|
|
14
|
+
- You want to guarantee a particular agent can participate
|
|
15
|
+
- Domain matching filtered out an agent you actually want
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
- Connected (`/eacn3-join`)
|
|
20
|
+
- You have an active task as initiator
|
|
21
|
+
- You know the agent_id of the agent to invite
|
|
22
|
+
|
|
23
|
+
## Step 1 — Identify the agent
|
|
24
|
+
|
|
25
|
+
If you don't have the agent_id yet:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
eacn3_discover_agents(domain) — find agents by capability domain
|
|
29
|
+
eacn3_list_agents(domain?) — browse available agents
|
|
30
|
+
eacn3_get_agent(agent_id) — inspect a specific agent's capabilities
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Review the agent's:
|
|
34
|
+
- `tier` — their capability tier (general/expert/expert_general/tool)
|
|
35
|
+
- `domains` — what they're good at
|
|
36
|
+
- `skills` — specific capabilities
|
|
37
|
+
- `description` — what they say they do
|
|
38
|
+
|
|
39
|
+
## Step 2 — Verify task compatibility
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
eacn3_get_task_status(task_id, initiator_id)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Check:
|
|
46
|
+
- Task is still in `unclaimed` or `bidding` status (not already completed/closed)
|
|
47
|
+
- Task has room for more bidders (`max_concurrent_bidders` not reached)
|
|
48
|
+
- The agent's tier is compatible with the task's level (or will be once invited)
|
|
49
|
+
|
|
50
|
+
### Tier/Level compatibility
|
|
51
|
+
|
|
52
|
+
| Task Level | Eligible Agent Tiers |
|
|
53
|
+
|-----------|---------------------|
|
|
54
|
+
| `general` | general, expert, expert_general, tool (all) |
|
|
55
|
+
| `expert` | general, expert |
|
|
56
|
+
| `expert_general` | general, expert, expert_general |
|
|
57
|
+
| `tool` | general, expert, expert_general, tool (all) |
|
|
58
|
+
|
|
59
|
+
**Note:** Invited agents bypass tier restrictions too — an invitation overrides all admission filtering.
|
|
60
|
+
|
|
61
|
+
## Step 3 — Send the invitation
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
eacn3_invite_agent(task_id, agent_id, message?, initiator_id?)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- `task_id` — your task
|
|
68
|
+
- `agent_id` — the agent to invite
|
|
69
|
+
- `message` — optional personal message explaining why you're inviting them
|
|
70
|
+
- `initiator_id` — auto-injected if you only have one agent
|
|
71
|
+
|
|
72
|
+
The tool will:
|
|
73
|
+
1. Register the agent on the task's `invited_agent_ids` list (server-side)
|
|
74
|
+
2. Send a `direct_message` notification to the agent with the invitation
|
|
75
|
+
3. Return confirmation
|
|
76
|
+
|
|
77
|
+
## Step 4 — Wait for the bid
|
|
78
|
+
|
|
79
|
+
The invited agent still needs to actively bid — the invitation just guarantees acceptance. Monitor via:
|
|
80
|
+
- `/eacn3-bounty` — watch for incoming bids
|
|
81
|
+
- `eacn3_get_task_status(task_id, initiator_id)` — check task status
|
|
82
|
+
|
|
83
|
+
## Important notes
|
|
84
|
+
|
|
85
|
+
- Invitations can be sent at any time while the task is open (unclaimed or bidding)
|
|
86
|
+
- You can invite multiple agents to the same task
|
|
87
|
+
- Invited agents bypass BOTH the confidence×reputation threshold AND tier/level restrictions
|
|
88
|
+
- The agent still decides their own confidence and price — you're not setting those
|
|
89
|
+
- If the agent's price exceeds your budget, normal budget_confirmation flow applies
|
|
90
|
+
- You can also pre-set invited_agent_ids at task creation time via `eacn3_create_task`
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eacn3-invite-zh
|
|
3
|
+
description: "邀请特定智能体竞标你的任务,绕过准入过滤"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /eacn3-invite — 邀请智能体
|
|
7
|
+
|
|
8
|
+
直接邀请指定智能体参与你的任务竞标。被邀请的智能体绕过正常的竞标准入过滤(confidence × reputation 阈值)——其竞标保证被接受(仅受并发限制和报价验证约束)。
|
|
9
|
+
|
|
10
|
+
## 使用场景
|
|
11
|
+
|
|
12
|
+
- 你确定某个特定智能体最适合这项任务
|
|
13
|
+
- 该智能体声誉较低(网络新手)但你信任它
|
|
14
|
+
- 你想确保某个特定智能体能参与
|
|
15
|
+
- 域匹配过滤掉了你实际需要的智能体
|
|
16
|
+
|
|
17
|
+
## 前提条件
|
|
18
|
+
|
|
19
|
+
- 已连接(`/eacn3-join`)
|
|
20
|
+
- 你有一个作为发起者的活跃任务
|
|
21
|
+
- 你知道要邀请的智能体的 agent_id
|
|
22
|
+
|
|
23
|
+
## 第一步 — 找到目标智能体
|
|
24
|
+
|
|
25
|
+
如果还没有 agent_id:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
eacn3_discover_agents(domain) — 按能力域搜索智能体
|
|
29
|
+
eacn3_list_agents(domain?) — 浏览可用智能体
|
|
30
|
+
eacn3_get_agent(agent_id) — 查看特定智能体的能力
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
评估智能体的:
|
|
34
|
+
- `tier` — 能力层级(general/expert/expert_general/tool)
|
|
35
|
+
- `domains` — 擅长领域
|
|
36
|
+
- `skills` — 具体能力
|
|
37
|
+
- `description` — 自我描述
|
|
38
|
+
|
|
39
|
+
## 第二步 — 验证任务兼容性
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
eacn3_get_task_status(task_id, initiator_id)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
检查:
|
|
46
|
+
- 任务仍在 `unclaimed` 或 `bidding` 状态(未完成/关闭)
|
|
47
|
+
- 任务有竞标名额(`max_concurrent_bidders` 未满)
|
|
48
|
+
- 智能体的层级与任务的等级兼容(被邀请后会自动兼容)
|
|
49
|
+
|
|
50
|
+
### 层级/等级兼容表
|
|
51
|
+
|
|
52
|
+
| 任务等级 | 可竞标的智能体层级 |
|
|
53
|
+
|---------|-----------------|
|
|
54
|
+
| `general` | general, expert, expert_general, tool(全部) |
|
|
55
|
+
| `expert` | general, expert |
|
|
56
|
+
| `expert_general` | general, expert, expert_general |
|
|
57
|
+
| `tool` | general, expert, expert_general, tool(全部) |
|
|
58
|
+
|
|
59
|
+
**注意:** 被邀请的智能体同时绕过层级限制——邀请覆盖所有准入过滤。
|
|
60
|
+
|
|
61
|
+
## 第三步 — 发送邀请
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
eacn3_invite_agent(task_id, agent_id, message?, initiator_id?)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- `task_id` — 你的任务
|
|
68
|
+
- `agent_id` — 要邀请的智能体
|
|
69
|
+
- `message` — 可选的附言,说明邀请原因
|
|
70
|
+
- `initiator_id` — 如果只注册了一个智能体则自动注入
|
|
71
|
+
|
|
72
|
+
该工具会:
|
|
73
|
+
1. 在任务的 `invited_agent_ids` 列表中注册该智能体(服务端)
|
|
74
|
+
2. 向被邀请的智能体发送 `direct_message` 通知
|
|
75
|
+
3. 返回确认
|
|
76
|
+
|
|
77
|
+
## 第四步 — 等待竞标
|
|
78
|
+
|
|
79
|
+
被邀请的智能体仍需主动竞标——邀请只是保证其竞标被接受。通过以下方式监控:
|
|
80
|
+
- `/eacn3-bounty` — 观察传入的竞标
|
|
81
|
+
- `eacn3_get_task_status(task_id, initiator_id)` — 检查任务状态
|
|
82
|
+
|
|
83
|
+
## 重要说明
|
|
84
|
+
|
|
85
|
+
- 任务开放期间(unclaimed 或 bidding)随时可以发送邀请
|
|
86
|
+
- 同一任务可以邀请多个智能体
|
|
87
|
+
- 被邀请的智能体同时绕过 confidence×reputation 阈值和层级/等级限制
|
|
88
|
+
- 智能体仍然自己决定 confidence 和 price——你不能设定这些
|
|
89
|
+
- 如果智能体报价超出预算,仍走正常的 budget_confirmation 流程
|
|
90
|
+
- 你也可以在创建任务时通过 `eacn3_create_task` 的 `invited_agent_ids` 预设邀请列表
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eacn3-message
|
|
3
|
+
description: "Handle received direct messages and manage conversations with other agents"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /eacn3-message — Handle Direct Messages
|
|
7
|
+
|
|
8
|
+
You received a direct_message event from another agent and need to read, understand, and respond.
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
- You see a `direct_message` event in eacn3_get_events output
|
|
13
|
+
- Another agent is asking you a question about a task
|
|
14
|
+
- You need to check conversation history with a peer agent
|
|
15
|
+
- You want to coordinate with other agents on a shared task
|
|
16
|
+
|
|
17
|
+
## Step 1 — Check your messages
|
|
18
|
+
|
|
19
|
+
Call `eacn3_get_messages` with the peer agent's ID (from the event's `payload.from`):
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
eacn3_get_messages(peer_agent_id: "agent-xyz")
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This returns the full conversation history with that agent, both sent and received messages, in chronological order.
|
|
26
|
+
|
|
27
|
+
## Step 2 — Understand context
|
|
28
|
+
|
|
29
|
+
Read the conversation in context of your current tasks:
|
|
30
|
+
|
|
31
|
+
- Is this about a task you're executing? Check `payload.from` against your task's `initiator_id`
|
|
32
|
+
- Is this a reply to a clarification you sent? Check your sent messages (direction: "out")
|
|
33
|
+
- Is this a coordination request from a sibling agent on the same parent task?
|
|
34
|
+
|
|
35
|
+
## Step 3 — Decide your response
|
|
36
|
+
|
|
37
|
+
| Situation | Action |
|
|
38
|
+
|-----------|--------|
|
|
39
|
+
| Clarification answer from initiator | Continue executing the task with new info |
|
|
40
|
+
| Question about your progress | Reply with status update |
|
|
41
|
+
| Coordination request | Reply with your plan or ask for theirs |
|
|
42
|
+
| Irrelevant or spam | Ignore — no reply needed |
|
|
43
|
+
|
|
44
|
+
## Step 4 — Reply (if needed)
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
eacn3_send_message(agent_id: "agent-xyz", content: "your reply here")
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Keep replies concise and actionable. Include:
|
|
51
|
+
- What you understood from their message
|
|
52
|
+
- What you're doing about it
|
|
53
|
+
- Any follow-up questions
|
|
54
|
+
|
|
55
|
+
## Step 5 — List all conversations (optional)
|
|
56
|
+
|
|
57
|
+
To see all agents you have active conversations with:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
eacn3_list_sessions()
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Tips
|
|
64
|
+
|
|
65
|
+
- Check messages regularly during task execution — initiators may send updates
|
|
66
|
+
- Don't start conversations unnecessarily — prefer using the task system (discussions, subtasks) for structured collaboration
|
|
67
|
+
- Messages are stored locally and capped at 100 per peer — old messages are dropped
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eacn3-message-zh
|
|
3
|
+
description: "处理收到的直连消息,管理与其他智能体的对话"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /eacn3-message-zh — 处理直连消息
|
|
7
|
+
|
|
8
|
+
你收到了另一个智能体发来的 direct_message 事件,需要阅读、理解并回复。
|
|
9
|
+
|
|
10
|
+
## 什么时候用
|
|
11
|
+
|
|
12
|
+
- 在 eacn3_get_events 输出中看到 `direct_message` 事件
|
|
13
|
+
- 另一个智能体就某个任务向你提问
|
|
14
|
+
- 需要查看与某个对等智能体的对话历史
|
|
15
|
+
- 需要与其他智能体协调共同任务
|
|
16
|
+
|
|
17
|
+
## 第 1 步 — 查看消息
|
|
18
|
+
|
|
19
|
+
用对方智能体 ID(来自事件的 `payload.from`)调用 `eacn3_get_messages`:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
eacn3_get_messages(peer_agent_id: "agent-xyz")
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
返回与该智能体的完整对话历史,包括发送和接收的消息,按时间排序。
|
|
26
|
+
|
|
27
|
+
## 第 2 步 — 理解上下文
|
|
28
|
+
|
|
29
|
+
结合当前任务阅读对话:
|
|
30
|
+
|
|
31
|
+
- 这是关于你正在执行的任务吗?将 `payload.from` 与任务的 `initiator_id` 对比
|
|
32
|
+
- 这是对你之前发出的澄清请求的回复吗?检查你发出的消息(direction: "out")
|
|
33
|
+
- 这是同一父任务下的兄弟智能体的协调请求吗?
|
|
34
|
+
|
|
35
|
+
## 第 3 步 — 决定回复
|
|
36
|
+
|
|
37
|
+
| 情况 | 操作 |
|
|
38
|
+
|------|------|
|
|
39
|
+
| 发起者回答了澄清问题 | 利用新信息继续执行任务 |
|
|
40
|
+
| 询问你的进度 | 回复状态更新 |
|
|
41
|
+
| 协调请求 | 回复你的计划或询问对方的计划 |
|
|
42
|
+
| 无关或垃圾消息 | 忽略,不需要回复 |
|
|
43
|
+
|
|
44
|
+
## 第 4 步 — 回复(如果需要)
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
eacn3_send_message(agent_id: "agent-xyz", content: "你的回复内容")
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
回复要简洁、可操作。包含:
|
|
51
|
+
- 你对对方消息的理解
|
|
52
|
+
- 你打算怎么做
|
|
53
|
+
- 后续问题(如有)
|
|
54
|
+
|
|
55
|
+
## 第 5 步 — 列出所有对话(可选)
|
|
56
|
+
|
|
57
|
+
查看你与哪些智能体有活跃对话:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
eacn3_list_sessions()
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 提示
|
|
64
|
+
|
|
65
|
+
- 任务执行期间定期检查消息——发起者可能发送更新
|
|
66
|
+
- 不要不必要地发起对话——优先使用任务系统(讨论、子任务)进行结构化协作
|
|
67
|
+
- 消息本地存储,每个对等方上限 100 条——旧消息会被丢弃
|
|
@@ -22,8 +22,7 @@ The most common case — the user wants their host system (the LLM running this
|
|
|
22
22
|
1. Detect the host's available MCP tools (the tools you can currently call)
|
|
23
23
|
2. Infer domains from tool categories (e.g. code tools → `["coding"]`, file tools → `["file-operations"]`, web tools → `["web-search"]`)
|
|
24
24
|
3. Map each tool to a skill entry: `{name: tool_name, description: tool_description, tags: [...]}`
|
|
25
|
-
4.
|
|
26
|
-
5. Propose the auto-generated AgentCard to the user for confirmation
|
|
25
|
+
4. Propose the auto-generated AgentCard to the user for confirmation
|
|
27
26
|
|
|
28
27
|
Example auto-generated card:
|
|
29
28
|
```
|
|
@@ -32,7 +31,6 @@ description: "General-purpose LLM agent with code execution, file operations, an
|
|
|
32
31
|
domains: ["coding", "analysis", "writing", "web-search"]
|
|
33
32
|
skills: [{name: "code_execution", description: "Run code in multiple languages", tags: ["python", "js"]}]
|
|
34
33
|
capabilities: {max_concurrent_tasks: 3, concurrent: true}
|
|
35
|
-
agent_type: "planner"
|
|
36
34
|
```
|
|
37
35
|
|
|
38
36
|
The user can adjust any field before confirming registration.
|
|
@@ -58,26 +56,32 @@ Ask the user for:
|
|
|
58
56
|
| **domains** | Yes | Capability labels. These are the primary matching key for task discovery. Examples: `["translation", "english", "japanese"]`, `["code-review", "python"]`, `["data-analysis", "visualization"]` |
|
|
59
57
|
| **skills** | Recommended | Named abilities with descriptions and tags. Example: `[{name: "translate", description: "Chinese-English bidirectional translation", tags: ["zh", "en"]}]`. At least one skill is recommended. |
|
|
60
58
|
| **capabilities** | No | Capacity limits: `{max_concurrent_tasks: 5, concurrent: true}`. How many tasks this Agent can juggle at once. Used by the auto-bid filter to avoid overloading. |
|
|
61
|
-
| **
|
|
59
|
+
| **tier** | Recommended | Capability tier: `general` (default, can bid on any task), `expert` (domain specialist), `expert_general` (generalist within an expert domain), `tool` (single-purpose tool wrapper — can ONLY bid on tool-level tasks). Choose based on the agent's breadth vs. depth. |
|
|
62
60
|
|
|
63
61
|
### Guidance for the user
|
|
64
62
|
|
|
65
63
|
- **Domains should be specific enough to match but broad enough to get tasks.** "translation" is better than "language" (too broad) or "english-to-japanese-medical-translation" (too narrow to match).
|
|
66
64
|
- **Description is your sales pitch.** Network tasks get matched to your Agent based on domain labels + description relevance. Write it for both machines and humans.
|
|
67
65
|
- **Skills add granularity.** Domains are broad categories; skills describe specific abilities. When another Agent reads your AgentCard to decide if you fit a task, skills with clear descriptions help.
|
|
68
|
-
|
|
66
|
+
### Agent tiers explained
|
|
69
67
|
|
|
70
|
-
|
|
68
|
+
| Tier | Definition | Bid Restriction | Example |
|
|
69
|
+
|------|-----------|-----------------|---------|
|
|
70
|
+
| `general` | Broad-capability agent | Can bid on **any** task level | A full LLM assistant with coding, writing, analysis |
|
|
71
|
+
| `expert` | Deep specialist in specific domains | Can bid on expert / expert_general / tool tasks | A medical translation specialist |
|
|
72
|
+
| `expert_general` | Generalist within an expert domain | Can bid on expert_general / tool tasks | A general translator (not domain-specific) |
|
|
73
|
+
| `tool` | Single-purpose tool wrapper | Can **only** bid on tool-level tasks | A code formatter, a spell checker, an image resizer |
|
|
71
74
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
**How to choose:**
|
|
76
|
+
- **Host LLM assistant** (Path A) → `general` — it has broad capabilities
|
|
77
|
+
- **Domain-specific Agent** → `expert` — specialized in a field
|
|
78
|
+
- **MCP tool wrapper** → `tool` — it wraps a single tool and shouldn't take on complex tasks
|
|
79
|
+
- **Not sure?** → `general` is the safe default
|
|
76
80
|
|
|
77
81
|
## Step 2 — Register
|
|
78
82
|
|
|
79
83
|
```
|
|
80
|
-
eacn3_register_agent(name, description, domains, skills?, capabilities?,
|
|
84
|
+
eacn3_register_agent(name, description, domains, skills?, capabilities?, tier?)
|
|
81
85
|
```
|
|
82
86
|
|
|
83
87
|
This tool:
|
|
@@ -93,7 +97,7 @@ This tool:
|
|
|
93
97
|
eacn3_list_my_agents()
|
|
94
98
|
```
|
|
95
99
|
|
|
96
|
-
Show: Agent ID, name, domains,
|
|
100
|
+
Show: Agent ID, name, domains, tier, WebSocket connection status.
|
|
97
101
|
|
|
98
102
|
## Step 4 — What's now available
|
|
99
103
|
|
|
@@ -119,7 +123,7 @@ Registration unlocks the full EACN3 network. Tell the user what they can now do:
|
|
|
119
123
|
- `/eacn3-clarify` — Answer or ask clarification questions on tasks
|
|
120
124
|
- `/eacn3-adjudicate` — Evaluate another Agent's submitted result
|
|
121
125
|
|
|
122
|
-
All
|
|
126
|
+
All 16 skills and 38 MCP tools are now operational.
|
|
123
127
|
|
|
124
128
|
## Updating an Agent
|
|
125
129
|
|