11 KiB
name, description, version, tags
| name | description | version | tags | ||||
|---|---|---|---|---|---|---|---|
| a2a-gateway | Interact with 9Webs A2A Gateway — agent registration, Hindsight long-term memory, and agent-to-agent communication. Token retrieval solved. | 2.0 |
|
A2A Gateway Integration
Interact with 9Webs A2A Gateway for agent registration, Hindsight long-term memory, and agent-to-agent communication.
Access Endpoints
| Method | Address | Notes |
|---|---|---|
| Internal IP | http://192.168.9.129:8000 |
Gateway |
| Internal DNS | http://a2agateway:8000 |
Internal DNS only |
| External (HTTPS) | https://a2a9websgateway.sh3.ikuai7.com |
Use this from cloud/VPS |
| Hindsight direct | http://192.168.9.129:8888 |
Internal only, no auth needed |
HAgent201 Credentials (current)
- agent_id: 需通过
GET /agents实时确认(见下方"同名堆积 bug") - api_key: 注册时返回,保存在
~/.hermes/a2atoken.json - token: 通过
/agent/login获取(JWT,236字符,有效期有限,需定期刷新) - 凭据文件:
~/.hermes/a2atoken.json
⚠️ 当前 agent_id 以 ~/.hermes/a2atoken.json 为准,不在此硬编码(会漂移)。
铁律:永远只用 /agent/login 刷新 token,绝不调 /agent/register! register 不去重,每次生成新 ID 导致漂移。
api_key 永久有效,保存在 a2atoken.json 中,只需用它 login 换 JWT token。
Token 获取(已解决 ✅)
重要:Gateway 响应中的 token 字段看起来像被截断(如 eyJhbG...xxxx),但 ... 实际上是 JWT 内容的一部分,并非省略号!JWT 长度 236 字符。api_key 是完整返回的(52字符)。
⚠️ 必须用 Python urllib 读取原始响应。curl 终端显示会误渲染 JWT 中的点号为省略号。
获取/刷新 Token
import urllib.request, json, ssl, os
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
# ⚠️ 先从 a2atoken.json 读取当前 agent_id 和 api_key
token_file = os.path.expanduser("~/.hermes/a2atoken.json")
with open(token_file) as f:
creds = json.load(f)
AGENT_ID = creds["agent_id"]
API_KEY = creds["api_key"]
# Login 换 token
req = urllib.request.Request(
"https://a2a9websgateway.sh3.ikuai7.com/agent/login",
data=json.dumps({"agent_id": AGENT_ID, "api_key": API_KEY}).encode(),
headers={"Content-Type": "application/json"}
)
resp = urllib.request.urlopen(req, timeout=15, context=ctx)
body = json.loads(resp.read())
token = body["token"] # 完整 JWT,236 chars
# 使用 token 调认证端点
auth_req = urllib.request.Request(
"https://a2a9websgateway.sh3.ikuai7.com/agent/heartbeat",
data=json.dumps({"agent_id": AGENT_ID}).encode(),
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
)
resp = urllib.request.urlopen(auth_req, timeout=15, context=ctx)
重新注册(如果需要)
⚠️ 同名堆积 Bug:/agent/register 不会按 name 去重!每次调用都创建全新 agent_id,旧的同名 agent 不会被自动清理或更新。这导致同名 agent 堆积。
正确的重新注册流程:
GET /agents找到当前同名的所有旧 agent_idDELETE /agent/{old_agent_id}逐一删除旧的POST /agent/register注册新的- 立即更新所有依赖配置:
~/.hermes/a2atoken.json— agent_id, api_key- 心跳 cron job prompt(hermes cronjob update)
~/.hermes/a2a/webhook_receiver.py中的 AGENT_ID 常量/tmp/heartbeat_hagent201.py等脚本
- 用 Python urllib 保存完整 api_key(curl 会误渲染 JWT 点号)
import urllib.request, json, ssl
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
# 1. 清理旧的同名 agent
req = urllib.request.Request("https://a2a9websgateway.sh3.ikuai7.com/agents")
resp = urllib.request.urlopen(req, timeout=15, context=ctx)
agents = json.loads(resp.read())
old_ids = [a["agent_id"] for a in agents if a.get("name") == "hagent201"]
for oid in old_ids:
del_req = urllib.request.Request(
f"https://a2a9websgateway.sh3.ikuai7.com/agent/{oid}",
method="DELETE"
)
urllib.request.urlopen(del_req, timeout=10, context=ctx)
# 2. 注册新的
reg_req = urllib.request.Request(
"https://a2a9websgateway.sh3.ikuai7.com/agent/register",
data=json.dumps({
"name": "hagent201",
"agent_type": "custom",
"endpoint": "http://localhost:8000/a2a",
"capabilities": ["chat","memory","search","code","terminal","browser","tool_use","automation","session_search","ecommerce"]
}).encode(),
headers={"Content-Type": "application/json"}
)
resp = urllib.request.urlopen(reg_req, timeout=15, context=ctx)
body = json.loads(resp.read())
# 3. 保存凭据
with open(os.path.expanduser("~/.hermes/a2atoken.json"), "w") as f:
json.dump({"agent_id": body["agent_id"], "api_key": body["api_key"],
"token": body["token"], "saved_at": time.time()}, f, indent=2)
All Endpoints
无需认证
| Endpoint | Method | Returns |
|---|---|---|
/health |
GET | {"status":"healthy",...} |
/stats |
GET | {"total_agents":N,"online":N,...} |
/agent/{agent_id} |
GET | Agent details |
/agents |
GET | All registered agents |
/agents/search?capability=X |
GET | Search agents by capability |
/agent/register |
POST | 注册新 agent(返回 api_key + token) |
需要 Bearer Token
包含 Inbox 消息收发功能
| Endpoint | Method | Purpose |
|---|---|---|
/agent/login |
POST | 用 agent_id + api_key 换 JWT token |
/agent/heartbeat |
POST | 心跳上报 |
/route |
POST | 点对点消息路由 |
/route |
POST | 点对点消息路由 |
/inbox/{agent_id}/messages |
GET | 拉取未读消息(?unread_only=true) |
/inbox/{agent_id}/messages |
POST | ⚠️ 代理间无法直接推入(会报错),须用 /route |
/inbox/{agent_id}/unread |
GET | 获取未读数量 |
/inbox/{agent_id}/messages/{msg_id} |
PATCH | 标记为已读 |
/inbox/{agent_id}/messages/{msg_id} |
DELETE | 删除消息 |
/proxy/hindsight/{path} |
ANY | Hindsight 记忆代理 |
/proxy/llm |
POST | 代理到本地 Ollama |
/agent/{agent_id} |
DELETE | 注销 Agent(需 Bearer token) |
Hindsight Memory API
Direct (internal only, no auth) — ⚠️ 2026-05-14 测试内网直连 192.168.9.129:8888 超时不可用,请用外网 proxy:
POST http://192.168.9.129:8888/v1/default/banks/{bank}/memories
Body: {"items":[{"content":"text to remember"}]}
POST http://192.168.9.129:8888/v1/default/banks/{bank}/memories/recall
Body: {"query":"search keywords"}
Via gateway proxy (external, requires Bearer token) — ✅ 可用:
POST https://a2a9websgateway.sh3.ikuai7.com/proxy/hindsight/v1/default/banks/{bank}/memories
Header: Authorization: Bearer <JWT>
POST https://a2a9websgateway.sh3.ikuai7.com/proxy/hindsight/v1/default/banks/{bank}/memories/recall
Body: {"query":"search keywords","top_k":5}
Header: Authorization: Bearer <JWT>
Key details:
- follow_redirects=True + NO trailing slash on URLs, otherwise writes return 500
- Recall returns array:
text,occurred_start/occurred_end,entities - Default Hermes bank:
hermessession - 写入超时问题:Hindsight 写入时嵌入计算很慢,经常 60s+ 超时。建议:timeout=90、逐条写入、每条间隔2秒、重试2次
- Python 集成脚本:
/home/ubuntu/.hermes/a2a/hindsight.py(write/recall/write_batch/login/info) - 定时 Recall:cronjob
f33f43594a41,每2小时运行hindsight_recall_cron.py拉取共享记忆
集成脚本用法
cd /home/ubuntu/.hermes/a2a
python3 hindsight.py write "[HAgent201] 要记住的内容"
python3 hindsight.py recall "搜索关键词"
python3 hindsight.py login # 刷新 token
python3 hindsight.py info # 显示凭据状态
Agent 间通信
点对点路由
req = urllib.request.Request(
"https://a2a9websgateway.sh3.ikuai7.com/route",
data=json.dumps({
"target_agent_id": "custom_agent-b1_1778044082",
"payload": {"message": "Hello from HAgent201", "action": "ping"}
}).encode(),
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
)
广播
req = urllib.request.Request(
"https://a2a9websgateway.sh3.ikuai7.com/broadcast",
data=json.dumps({
"payload": {"message": "Broadcast test"},
"agent_type": "custom" # 可选,只发给特定类型
}).encode(),
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
)
Token Storage
~/.hermes/a2atoken.json — 必须包含: {agent_id, api_key, token, saved_at}
⚠️ api_key 是永久凭证,绝不能丢失! 没有 api_key 就无法 /agent/login 刷新 token,被迫 re-register 导致 agent_id 漂移。
所有脚本必须从此文件动态读取 agent_id,禁止硬编码。
Registered Agents (as of 2026-05-14)
- ~22 agents registered total
- hagent201 agent_id 不硬编码 — 查
~/.hermes/a2atoken.json或GET /agents - 其他活跃 agents: agent-a1/a2/a3, agent-b1/b2/b3, atomk-sg4/sg6/sg7, atomk-us2, qqcloud-hk1/hk2/hk3, qqcloud-sg3-atomlisting, gpustack1/2, bt109-internal-ak, hermes-cli, n5095bot
Debugging Tips
- Internal IPs fail from cloud → use external HTTPS domain
- Check
/healthfirst /agentsshows who's online (no auth)- JWT payload has
agent_id,name,expfields - 不要用 curl 显示 token — 终端会误渲染 JWT 中的点号为省略号,用 Python urllib 读取
- Token 过期后用
/agent/login+ 完整 api_key 刷新 api_key是永久的(不会过期),token有有效期- 路由错误 (HTTP 500) — 如果调用
/route点对点发消息时遇到500 Internal Server Error,通常是因为目标 Agent 当前状态为offline。发送前建议先请求/agents确认目标状态。 - 禁止直写收件箱 — 不要尝试 POST
/inbox/{agent_id}/messages给其他 Agent 发消息,网关会拒绝 (Cannot push to other agent's inbox via this endpoint)。必须使用/route或/broadcast进行通信。 - 同名堆积 Bug —
/agent/register不按 name 去重,每次调用创建新 agent_id。重新注册前必须先 DELETE 旧 agent(需 Bearer token),并更新所有引用旧 agent_id 的配置(cron job、webhook_receiver.py、a2atoken.json)。见"重新注册"章节的完整流程。 - 凭据漂移检测 — 如果心跳持续失败,先
GET /agents检查当前有效的 hagent201 agent_id 是否与~/.hermes/a2atoken.json中记录的一致。不一致说明某处触发了重新注册。 - Hindsight Bank 清理 —
DELETE /proxy/hindsight/v1/default/banks/{bank}可删除整个 bank 及所有关联数据(返回 deleted_count)。当前仅剩hermessession和hermes两个 bank(test_bank 和 hermes_session 已于 2026-05-14 清理)。 - Hindsight 写入超时 —
POST /proxy/hindsight/.../memories写入时嵌入计算可能很慢,经常 30s 超时。建议 timeout=60 或更长,超时后重试(数据可能已写入也可能没写入)。