@ adonis-agora/ 代理服务器
治理、持久支持的AI代理(聊天+工具调用+治理) 阿多尼斯·贾克 部分 阿戈拉语Name 生态系统.
包裹是两样东西 彼此上分层:
- A 类 框架不可知代理循环 —— 说
runAgentLoop(deps, input, hooks)驱动一个模型 工具 模型对照一套SPI(模型/存储/定额/角色/沉入/跑道/治理). 这个hooks接缝( 接缝)step编号 :awaitApproval编号 :openSink编号 :runAgent)让同样的循环体运行 正在处理或作为可重复播放的持久工作流程(通过)@adonis-agora/durable,可选对等点). - 一个 AdonisJS 整合外壳 - 服务提供者,
defineConfig,HTTP线路(/agent/*, (中文(简体) ),/agent/governance/*, (中文(简体) ),/agent/attachments),路西德后置商店,工具发现来自app/agent_tools,RAG( pgvector 或 Qdrant 检索器, 加上 PageIndex 类树导航 long 文档),一个被规范的只读 SQL 工具,以及一个回放聊天钩.
read 工具自动执行, action 人类批准工具门(HITL),以及 agent 工具代表
给另一个有名的特工.
组成部分登记册和服务器渲染
工具支持 a present 钩在功能上和装饰上都有. 在每个应用程序中注册自定义组件,在网络屏幕和静态导出之间共享React渲染器,并为您自己的送出适配器生成已加成的PNG/PDF表格和图表.
见 组件渲染指南 用于完整的示例、图案、文本倒置和抓取配置.
React 本地化的 Generative UI 沙盒
@adonis-agora/agent/react-native/genui 绘制沙盒组件( e)ui__sandbox在一个坚硬的
react-native-webview - 网络iframe的文档和CSP, 相同的检查 agent.send 桥 -
并再出口 " React " 本地安全基因供应商和部件(从这里进口)
应用程序,不是来自 /react/genui) (中文(简体) ). 安装 react-native-webview (可选对等),然后:
import { createNativeSandboxRenderer, GenuiProvider } from '@adonis-agora/agent/react-native/genui'
const Sandbox = createNativeSandboxRenderer({ theme: { vars: tokens }, baseUrl: 'https://api.example.com/agent' })
<GenuiProvider registry={{ Sandbox }} onAction={chat.sendUiAction}>…</GenuiProvider>
见 本地反应中的沙盒。 。 。 .
安装
pnpm add @adonis-agora/agent
node ace configure @adonis-agora/agent
configure 注册提供者,电线 ASSEMBLER init 生成已键入的钩子
app/agent_tools 枪管( 如不到位, 倒回运行时扫描) , 发布 config/agent.ts,以及
发布迁移情况——基干表、平面图 RAG-chunk表和树导航
表格(删除您不使用的任何表格,例如,如果您通过 Qdrant 检索到的 pgvector 迁移,
或树移,如果您不导航长文档; 运行 node ace migration:run 其余部分).
仅 ai (或手卷出) ModelProvider),并严格要求有模范工厂. 所有东西
换句话说 选项对等点,仅在配置时懒惰地导入 :
| 端点 | 需要时间 |
|---|---|
ai (单位:千美元)^7.0.0(中文(简体) ) | aiSdkModel ——Vercel AI SDK v7适配器(@adonis-agora/agent/ai-sdk(中文(简体) ) |
@adonisjs/lucid (单位:千美元)^22.4.0(中文(简体) ) | stores.lucid(),定价,治理读取模型,数据工具的 db |
@adonisjs/redis (单位:千美元)^9.2.0(中文(简体) ) | tokenSinks.redis() ——多replica SSE 令牌流出 |
@adonis-agora/durable (单位:千美元)^0.8.0(中文(简体) ) | durable: true ——再玩安全耐用跑道(@adonis-agora/agent/durable(中文(简体) ) |
@adonis-agora/authz (单位:千美元)^0.4.0(中文(简体) ) | AuthzActorResolver 编号 : AuthzToolAuthorizer (单位:千美元)@adonis-agora/agent/authz(中文(简体) ) |
@adonis-agora/telescope (单位:千美元)^0.4.0(中文(简体) ) | 望远镜监视器扩展( U)@adonis-agora/agent/telescope(中文(简体) ) |
@qdrant/js-client-rest (单位:千美元)^1.11.0(中文(简体) ) | retrievers.qdrant({...}) |
node-sql-parser (单位:千美元)^5.3.0(中文(简体) ) | 被监管者 dataTool (单位:千美元)@adonis-agora/agent/data(中文(简体) ) |
react (单位:千美元)^18 编号 : ^19, (中文(简体) ), @ai-sdk/react 财务报告和审定财务报表 ai | AgentProvider 编号 : useAgentChat (单位:千美元)@adonis-agora/agent/react(中文(简体) ) |
配置
仅 model 需要——选取 store 按名称(内存、单进程商店的缩写):
// config/agent.ts
import { defineConfig, stores, AuthActorResolver } from '@adonis-agora/agent'
import { aiSdkModel } from '@adonis-agora/agent/ai-sdk'
import { openai } from '@ai-sdk/openai'
export default defineConfig({
model: () => aiSdkModel(openai('gpt-4o-mini')), // any Vercel AI SDK v7 `LanguageModel`
store: 'lucid',
stores: { lucid: stores.lucid(), memory: stores.memory() },
actorResolver: new AuthActorResolver(), // defaults to one that THROWS — an identity is never fabricated
})
定价(costUsd 和每个转弯 /agent/governance/* 读取两个默认的路由到镜像
store 当它 stores.lucid() (相同的连接,表格自动创建) – 覆盖到
pricingStore 编号 : governanceQueries,或 false 以禁用. sink 默认为进程内符号
下沉; 通过 tokenSinks.redis({...}) 所以任何舱都可以服务 任何运行的SSE流.
使用
聊天——供应商为您挂载 HTTP API
没有可以写入的控制器: 一旦配置, 提供者本身会挂载 POST /agent/chat (开始)
a run and SSE -- protect the sorder stream),并接通了符号流, GET /agent/chat/:runId/stream (重接),线 CRUD,
高ITL核准/拒绝 action 工具、配额和——何时 governanceQueries 设置了——
/agent/governance/* 读取路线。 每个路线都解决了演员本身的问题(失败时401);a
threadId 转至 chat 必须属于打电话者.
从反应中驱动它 @adonis-agora/agent/react 整个无头层(历史、恢复、a)
消息队列、 批准、 附件、 线索等, 带有会话 cookie 和 屏蔽 CSRF 标志
已连接 :
// npm i @ai-sdk/react ai
import { AgentProvider, useAgentChat } from '@adonis-agora/agent/react'
export default function ChatPage() {
return (
<AgentProvider>
<Chat />
</AgentProvider>
)
}
function Chat() {
const { transcript, composer, queue } = useAgentChat()
return (
<form onSubmit={(e) => (e.preventDefault(), void composer.submit())}>
{transcript.items.map((item) => (
<p key={item.id}>{item.role}: {item.text}</p>
))}
{queue.items.map((m) => <p key={m.id}>(waiting) {m.text}</p>)}
<input value={composer.text} onChange={(e) => composer.setText(e.target.value)} />
<button disabled={!composer.canSend}>Send</button>
</form>
)
}
钩子船在阿戈拉。 其协议仍然与Aviary兼容,但安装和 释放是独立的。 没有反应, 请使用无框架流客户端 :
import { createAgentChatClient } from '@adonis-agora/agent/client'
const client = createAgentChatClient({ basePath: '/agent' })
const { parts } = await client.send({ body: { message: 'hi' }, onParts: (parts) => render(parts) })
写入一个规范的工具
工具是自动发现的 app/agent_tools。 。 。 . ReadTool 自动执行; ActionTool 需求
运行前的人类批准:
// app/agent_tools/allocation_queue.ts
import { z } from 'zod'
import { ReadTool } from '@adonis-agora/agent'
import type { AiToolCtx } from '@adonis-agora/agent'
export default class AllocationQueue extends ReadTool<{}, Row[]> {
static tool = {
name: 'allocation_queue',
description: 'Lists pending allocation requests for the current tenant.',
input: z.object({}),
ability: 'agent.coordinator.queue.read',
}
async execute(_input: {}, ctx: AiToolCtx): Promise<Row[]> {
return db.from('allocations').where('tenant_ref', ctx.actor.tenantRef)
}
}
一个 ActionTool 写在某处 写在书上和检查点上 记录着两篇:
他们之间死亡的工人重新运行了恢复工具. ctx.idempotencyKey
(单位:千美元)<runId>:<toolCallId>)每一次执行一次呼叫,都一样——传递到下游
一能钥匙(供应商的) Idempotency-Key,一个独特的列 id 工作流程中的工具
因此,第二次尝试降落在第一次.
管理只读 SQL
@adonis-agora/agent/data 船舶 dataTool ——一个已失效的SQL工具:它需要一个明确的,
基于角色的表格允许列表,在可选的每行租户范围重写(从调用演员的
tenantRef),注入行数 LIMIT在他们撞到模型前 切入过大的结果
上下文。 登记为静态工具 config/agent.ts (单位:千美元)defineConfig({ tools: [dataTool({...})] })(中文(简体) )
或从一个 app/agent_tools/ 模块 :
import { dataTool } from '@adonis-agora/agent/data'
import db from '@adonisjs/lucid/services/db'
export const executeSql = dataTool({
db,
tableAccess: {
roleGroups: { ADMIN: ['billing'] },
tablesByGroup: { billing: ['orders', 'invoices'] },
},
tenant: { tenantColumn: 'tenant_ref', scopedTables: ['orders', 'invoices'] },
maxRows: 200,
})
护栏-PII、秘密、即时注射、工具中毒
@adonis-agora/agent/guardrails 把探测器和规则引擎 安装在循环的处理器接合器上,
哪个 config/agent.ts 现在当作 inputProcessors 编号 : outputProcessors数字 :
// config/agent.ts
import { createGuardrails } from '@adonis-agora/agent/guardrails'
const guardrails = createGuardrails({
pii: 'redact', // reversible: the model sees [EMAIL_1], the reader the address
secrets: 'block',
injection: { threshold: 0.6 }, // the prompt and every tool result; default action: block
toolPoisoning: true, // guardrails.screenTool, for `mcpServers[].screen`
rules: (ctx) => rulesForTenant(ctx.actor?.tenantRef), // more rules, resolved per scan
onEvent: (event) => audit(event), // hits carry fingerprints, never values
})
export default defineConfig({
model: () => aiSdkModel(openai('gpt-4o-mini')),
inputProcessors: [guardrails.input],
outputProcessors: [guardrails.output],
mcpServers: [{ name: 'docs', transport: { type: 'http', url }, screen: (t) => guardrails.screenTool(t) }],
})
被屏蔽的提示失败运行( E)ProcessorFailedError 由一 GuardrailBlockedError页:1
被屏蔽的工具结果被扣留并打开; 被屏蔽的答案或工具呼叫是
OutputRejectedError。 。 。 . guardrails.wrapTool(name, handler) 将占位符恢复到工具的
参数和运行 tool_args 规则他们。 输出处理器声明 incremental,所以请
答案持续流出。 探测器detectPii 与Luhn/CPF/CNPJ/IBAN核对, detectSecrets, (中文(简体) ),
scoreInjection, (中文(简体) ), scoreToolText和 scan 独立工作。 在阿戈拉当地的护卫舰执行船;它不需要一个Aviary核心包.
框架不可知核心(无AdonisJS)
runAgentLoop(deps, input, hooks) 是一个共享的转会机构, 既包括进程(InlineAgentRunner(中文(简体) )
和能耐的跑道 hooks 说明它装的是哪个 直接锻炼(例如:
a test),与内相相双从 @adonis-agora/agent/testing数字 :
import { runAgentLoop, ToolRegistry, DefaultRolesPolicy } from '@adonis-agora/agent'
import {
FakeModelProvider,
echoScript,
InMemoryAgentStore,
InMemoryTokenStreamSink,
} from '@adonis-agora/agent/testing'
const sink = new InMemoryTokenStreamSink()
const { text } = await runAgentLoop(
{
model: new FakeModelProvider(echoScript('hi there')),
store: new InMemoryAgentStore(),
registry: new ToolRegistry(),
rolesPolicy: new DefaultRolesPolicy(),
day: '2026-07-21',
systemPrompt: 'You are a helpful assistant.',
},
{ threadId: 'thread-1', actor: { id: 'user-1', roles: ['USER'] }, userText: 'hi' },
{
runId: crypto.randomUUID(),
openSink: () => sink.open('run-1'),
awaitApproval: async () => 'approve',
step: (_name, fn) => fn(),
},
)
盘子
node ace configure @adonis-agora/agent 还登记嵌入式治理控制台——
@adonis-agora/agent-dashboard 反应 SPA, 直接捆入 @adonis-agora/agent属于自己的 dist/
在建设时间. 没有单独的安装,没有单独的提供者注册. 它会上升
<path>/dashboard (默认) /agent/dashboard一次) governanceAuthorize 已配置——每个面板
但配额读取交叉角色 /agent/governance/* 没有那道门,那道路就不存在了
因此控制台拒绝上载(并附有靴子警告说明原因)而不是装载和404
每个面板上 :
// config/agent.ts
export default defineConfig({
// ...
governanceAuthorize: (actor) => actor.roles?.includes('ADMIN') ?? false,
// dashboard: { enabled: true, path: '/agent/dashboard', authorize: (actor) => actor.roles?.includes('ADMIN') ?? false },
})
两者 governanceAuthorize 财务报告和审定财务报表 dashboard.authorize 返回一个 AuthorizeResult —— 说
boolean | { allowed: boolean; reason?: 'unauthenticated' | 'forbidden' } (从
@adonis-agora/agent 财务报告和审定财务报表 @adonis-agora/agent/dashboard) (中文(简体) ). true编号 :{ allowed: true } 允许;
{ allowed: false, reason: 'unauthenticated' } 答题 401· ; false, (中文(简体) ), { allowed: false }, (中文(简体) ),
reason: 'forbidden' 或掷出答案 403。控制台用其拒绝访问的页面,即
与 JSON 的治理路径; 重定向的钩子本身被保存 .
见 治理仪表板 对于完整的配置形状.
独立安装( 仍然支持)
@adonis-agora/agent-dashboard 船舶作为自己的可安装包 装自有供应商,用于
需要其独立发布cadence或在嵌入式提供者之前配置的应用程序
已存在 :
pnpm add @adonis-agora/agent-dashboard
node ace add @adonis-agora/agent-dashboard
它读取相同的 config('agent').dashboard 块。 仅登记两个供应商中的一个——安装
两者在同一路径中都将AdonisJS的"重复路线"出错投出出后靴.
诊断
运行时事件流经 @adonis-agora/agent/telescope监视器
@adonis-agora/telescope 已安装,同时
框架不可知性 diagnostics 从根切入点导出的事件类型.
测试
@adonis-agora/agent/testing 船舶 FakeModelProvider 和内膜双倍的商店,水槽,
配额和治理 SPI,因此,代理循环可以决定性地进行,没有DB,Redis,
或者一个真正的模型提供者.
链接
- 重现 : https://github.com/Davide Carvalho/ados-agent 互联网档案馆的存檔,存档日期2013-12-21
- 更改日志 : https://github.com/DavideCarvalho/adonis-agent/blob/master/packages/adonis/CHANGELOG.md 互联网档案馆的存檔,存档日期2013-12-22
- 配套软件包( 也自动嵌入, 参见 盘子 上文:
@adonis-agora/agent-dashboard
许可证
麻省理工学院