Documentation
¶
Overview ¶
Package ack 在 trpc-agent-go 的 AG-UI 协议栈之上提供工具调用许可 (tool permission)能力。
工具按层级(Tier)分类:默认放行(allow)、需人工确认(confirm)、 禁用(deny)。每次工具调用先经许可评估:外部策略源(PolicySource, 如风控)可介入裁决,用户预先授予的许可(Grant,会话级/全局级)可 满足确认要求,仅当无任何放行依据时才阻塞等待人工决定。全部自动 授权终态可经 WithPermissionObserver 外报宿主审计;人工决定不通知, 归宿主 Decide 路由。
人工确认的完整生命周期由网关(Gateway)承载:
- 直接路径(live):发出确认的运行存活时,决定唤醒阻塞的运行 继续执行,事件仍走原始 SSE/follow 流;
- 恢复路径(recovery):运行已不存在(如服务重启)时,由网关 代执行工具或合成拒绝结果,并拉起一次续跑运行,前端经 /history follow 流读取。
前端经 AG-UI 自定义事件 tool_confirmation 渲染确认卡片,经 ackhttp.Mount 挂载的 HTTP 路由提交决定。最小接入:
gw := ack.New(svc,
ack.WithApp("biz"), // 须与 AG-UI runner 的 AppName 一致
ack.WithTiers(map[string]ack.Tier{"delete_note": ack.TierConfirm}),
ack.WithGrants(ack.MemoryGrants()),
ack.WithStaticTools(readNote, deleteNote),
)
r := aguirunner.New(coreRunner,
aguirunner.WithAppName("biz"),
aguirunner.WithSessionService(svc),
aguirunner.WithRunOptionResolver(gw.RunOptionResolver()),
)
_ = gw.Bind(r)
ackhttp.Mount(mux, gw)
完整契约(事件、状态存储、HTTP 形状、不变量)见 docs/module_design.md。
Index ¶
- Constants
- Variables
- type Basis
- type DecideResult
- type Decision
- type DenyTexts
- type Gateway
- func (g *Gateway) Bind(r ResumeRunner) error
- func (g *Gateway) Decide(ctx context.Context, d Decision) (DecideResult, error)
- func (g *Gateway) Pending(ctx context.Context, sessionID string) ([]PendingItem, error)
- func (g *Gateway) PolicyFor(sessionID string) tool.PermissionPolicyFunc
- func (g *Gateway) RunOptionResolver() ...
- type Grant
- type GrantQuery
- type GrantSource
- type NamedPolicy
- type Option
- func WithApp(name string) Option
- func WithDefaultTier(t Tier) Option
- func WithDenyTexts(t DenyTexts) Option
- func WithGrants(gs GrantSource) Option
- func WithLogger(l *slog.Logger) Option
- func WithNamedPolicies(ps ...NamedPolicy) Option
- func WithPermissionObserver(ob PermissionObserver) Option
- func WithPolicies(src ...PolicySource) Option
- func WithStaticTools(tools ...tool.Tool) Option
- func WithTierFunc(fn func(ctx context.Context, call ToolCall) Tier) Option
- func WithTiers(m map[string]Tier) Option
- func WithTools(res ToolResolver) Option
- func WithUser(id string) Option
- func WithUserFunc(fn func(ctx context.Context, threadID string) string) Option
- type Payload
- type PendingItem
- type PermissionEvent
- type PermissionObserver
- type PolicySource
- type ResumeRunner
- type Scope
- type Tier
- type ToolCall
- type ToolResolver
- type Verdict
Constants ¶
const ( // PathLive 直接路径:发出确认的运行仍存活,决定唤醒阻塞的运行。 PathLive = "live" // PathRecovery 恢复路径:运行已不存在,网关代执行/合成结果并续跑。 PathRecovery = "recovery" )
决定实际生效的路径。
const ( // EventName 是携带确认 Payload 的 AG-UI 自定义事件名。 EventName = "tool_confirmation" // StateKey 是待确认表在 Session.State 中的键, // 让"等待确认"状态可以在服务重启后存活。 StateKey = "__pending_tool_confirmation__" // StatusPending 表示确认正等待用户决定。 StatusPending = "pending" // StatusApproved 表示用户已同意该确认。 StatusApproved = "approved" // StatusDenied 表示用户已拒绝该确认。 StatusDenied = "denied" )
以下常量是 wire 与存储的兼容性契约:升级只增不改,否则遗留待确认 指针失联、前端事件配对失效。
Variables ¶
var ( // ErrNotFound 表示确认或会话不存在;含已决定(或已取消)后的 // 重复决定与并发决定中的后到者。 ErrNotFound = errors.New("ack: confirmation not found") // ErrNotBound 表示恢复路径需要续跑 runner 但未 Bind。 ErrNotBound = errors.New("ack: resume runner not bound") // ErrRunActive 表示续跑时会话上仍有运行进行;对框架运行冲突 // 错误包装,errors.Is 可判。 ErrRunActive = errors.New("ack: run active on session") )
Functions ¶
This section is empty.
Types ¶
type Basis ¶
type Basis string
Basis 是授权终态的生效依据词表:一次工具调用的许可流程结束时, 标明放行或拒绝由哪条依据产生。该类型同时用作评估管线的内部依据 (evaluate 的返回值,供日志输出),内部值 basisForced / basisBaseline 保持未导出、不进入终态事件。
const ( // BasisTier 层级依据:工具的许可层级直接放行或禁用。 BasisTier Basis = "tier" // BasisVerdict 判定依据:首个 deny 判定的策略源拒绝。 BasisVerdict Basis = "verdict" // BasisEndorsement 背书依据:首个 allow 判定的策略源将 confirm // 层级降级为放行。 BasisEndorsement Basis = "endorsement" // BasisGrant 许可依据:人工预授予的许可命中放行。 BasisGrant Basis = "grant" // BasisDuplicate 同会话重复确认 ID 的防御性放行。 BasisDuplicate Basis = "duplicate" // BasisCanceled 运行取消或超时的结算拒绝。 BasisCanceled Basis = "canceled" // BasisPersistFailed 确认请求持久化失败的结算拒绝。 BasisPersistFailed Basis = "persist-failed" )
type DecideResult ¶
type DecideResult struct {
Path string // PathLive | PathRecovery
}
DecideResult 是 Decide 的结果。
type Decision ¶
type Decision struct {
SessionID string // 会话 ID
ConfirmationID string // 确认 ID
Approved bool // true=同意,false=拒绝
DecidedBy string // 决定人;留空取网关身份
Remember Scope // 空=不生成许可;同意时按作用域写入许可源
}
Decision 是一次人工决定的完整参数;以结构体承载演进空间, 后续以增字段方式扩展。
type DenyTexts ¶ added in v0.2.1
type DenyTexts struct {
// HumanDenied 人工拒绝(Decide 结算)的文案;live 与 recovery 路径一致。
HumanDenied func(call ToolCall) string
// TierDisabled 层级 deny 或策略 deny 判定拒绝的文案。
TierDisabled func(toolName string) string
// Canceled 运行取消或超时结算拒绝的文案。
Canceled string
// PersistFailed 待确认指针持久化失败结算拒绝的文案。
PersistFailed string
Unavailable func(toolName, detail string) string
}
DenyTexts 定制各类拒绝时返回给模型的文案。零值字段使用库默认文案 (英文,含"不得重试"指令),自定义文案须自行保留该约束。
type Gateway ¶
type Gateway struct {
// contains filtered or unexported fields
}
Gateway 是库的核心对象:评估工具调用处置(放行/确认/拒绝),并承载 人工确认的完整生命周期——登记等待者、持久化待确认指针、结算决定、 恢复孤儿确认。Gateway 并发安全,可被多个 goroutine 同时调用。
网关不拥有会话存储、许可源与续跑 runner 的生命周期,三者由业务 构造与关闭。
func (*Gateway) Bind ¶
func (g *Gateway) Bind(r ResumeRunner) error
Bind 注入恢复路径续跑使用的 AG-UI runner;传入 nil 返回错误。 恢复路径触发时未 Bind 的,Decide 返回 ErrNotBound。
func (*Gateway) Decide ¶
Decide 结算一次人工决定,返回实际生效的路径(PathLive / PathRecovery)。 ctx 约束持久化与续跑的启动,不等待续跑完成。 同一确认的并发决定先到者生效,后到者返回 ErrNotFound。
func (*Gateway) PolicyFor ¶
func (g *Gateway) PolicyFor(sessionID string) tool.PermissionPolicyFunc
PolicyFor 返回单个会话的权限策略:该会话的每次工具调用先经许可评估, 评估为确认的调用进入人工确认流程。供直接使用 core runner 的业务挂载; 经 AG-UI runner 接入的业务用 RunOptionResolver。
func (*Gateway) RunOptionResolver ¶
func (g *Gateway) RunOptionResolver() func(ctx context.Context, in *adapter.RunAgentInput) ([]agent.RunOption, error)
RunOptionResolver 把许可策略适配为 aguirunner.WithRunOptionResolver 需要的形式,使每次 AG-UI 运行(含恢复路径的续跑)都挂上该策略。
type Grant ¶
type Grant struct {
UserID string // 归属用户
SessionID string // 非空即会话级;空即全局级
ToolName string
CreatedBy string // 决定来源(人工决定的 DecidedBy)
CreatedAt int64 // 毫秒时间戳
}
Grant 是用户对某工具的预先授权,可满足 confirm 层级的确认要求; 强制确认(策略源 confirm 判定触发)不可被许可满足。
type GrantQuery ¶
GrantQuery 是许可查询条件。
type GrantSource ¶
type GrantSource interface {
Lookup(ctx context.Context, q GrantQuery) (Grant, bool)
Save(ctx context.Context, g Grant) error
}
GrantSource 是许可存储的接入点,由业务实现(如用户设置系统)。 生命周期归业务管理(列出/吊销/过期);库仅在许可评估时读取、在 Remember 决定时写入。Lookup 须按"会话级先于全局级"的次序命中。
type NamedPolicy ¶
type NamedPolicy struct {
Name string
Source PolicySource
}
NamedPolicy 是带名字的策略源:名字进入授权终态事件的 Source 字段, 标明生效依据来自哪个外部裁决系统;空名字视同匿名(Source 为空)。
type Option ¶
type Option func(*options)
Option 配置 Gateway。
func WithDefaultTier ¶
WithDefaultTier 设置未分级工具的层级(默认 TierAllow)。
func WithDenyTexts ¶ added in v0.2.1
WithDenyTexts 定制各类拒绝时返回给模型的文案(见 DenyTexts); 零值字段保持默认文案(英文、含"不得重试"指令)。
func WithGrants ¶
func WithGrants(gs GrantSource) Option
WithGrants 设置许可源;缺省时许可评估视为永不命中,Remember 被忽略。
func WithNamedPolicies ¶
func WithNamedPolicies(ps ...NamedPolicy) Option
WithNamedPolicies 设置具名策略源,名字进入授权终态事件的 Source 字段,标明生效依据来自哪个外部裁决系统;与 WithPolicies 合成一条 咨询链(具名源在前、匿名源在后)。空名字视同匿名。
func WithPermissionObserver ¶
func WithPermissionObserver(ob PermissionObserver) Option
WithPermissionObserver 设置授权终态观察者,订阅全部自动授权终态; 人工决定不通知,归宿主 Decide 路由审计。缺省 nil 零行为, 调用契约见 PermissionObserver。
func WithPolicies ¶
func WithPolicies(src ...PolicySource) Option
WithPolicies 设置匿名策略源,每次工具调用逐个同步咨询;与 WithNamedPolicies 合成一条咨询链(具名源在前、匿名源在后),匿名 登记不产生授权终态事件的 Source。
func WithStaticTools ¶
WithStaticTools 是 WithTools 的静态糖:直接给出工具集合, 裁决时刻按声明名解析。
func WithTierFunc ¶
WithTierFunc 设置动态分级,可依据入参分类;优先于静态表, 静态表优先于默认层级。
func WithTools ¶
func WithTools(res ToolResolver) Option
WithTools 设置工具解析器:恢复路径代执行时调用,返回"工具名 → 可调用工具"。缺省时同意的孤儿确认降级为"工具不可用"拒绝。
type Payload ¶
type Payload struct {
ConfirmationID string `json:"confirmationId"` // 确认 ID(即工具调用 ID)
ToolCallID string `json:"toolCallId"` // 关联的工具调用 ID
ToolName string `json:"toolName"` // 工具名
Arguments json.RawMessage `json:"arguments,omitempty"` // 工具入参(JSON)
SessionID string `json:"sessionId"` // 所属会话 ID
Status string `json:"status"` // pending | approved | denied
DecidedBy string `json:"decidedBy,omitempty"` // 做出决定的用户
CreatedAt int64 `json:"createdAt"` // 创建时间(毫秒时间戳)
}
Payload 是一次工具确认的完整描述:随 AG-UI CustomEvent 下发前端, 同时以待确认指针的形式持久化在 Session.State 中。
func (Payload) CustomEvent ¶
func (p Payload) CustomEvent() *aguievents.CustomEvent
CustomEvent 把 Payload 包装为 AG-UI 自定义事件。
type PendingItem ¶
PendingItem 是待确认列表项;Live 标记阻塞中的运行是否仍存活 (false 表示已成孤儿,例如服务重启之后)。
type PermissionEvent ¶
type PermissionEvent struct {
// Call 是发生授权的调用视图。
Call ToolCall
// Allowed 是终态是否放行。
Allowed bool
// Basis 是生效依据,取值见 Basis 词表。
Basis Basis
// Source 是生效的具名策略源名:Basis 为 verdict 或 endorsement
// 时是首个生效源的名字,其余依据与匿名策略源为空。已知信息损失:
// 策略源咨询出错按 confirm 判定处理(fail-safe),该调用若最终以
// canceled 结算,事件不携带出错源的名字,出错细节以网关日志为准。
Source string
}
PermissionEvent 是一次工具调用的授权终态:该调用的许可流程已结束, 结论不再变更。人工决定(Decide 结算,live 与 recovery 路径均是) 不产生事件——每次工具调用恰好一条授权终态:要么 PermissionEvent、 要么 Decide 结算,二者互斥且共同覆盖全部调用;人工决定由宿主在 Decide 自身的路由与日志中审计。
type PermissionObserver ¶
type PermissionObserver func(ctx context.Context, event PermissionEvent)
PermissionObserver 订阅网关产出的全部自动授权终态,供宿主外报审计。 网关在授权流程结束的同步路径上回调:回调应快速返回,重负载的外报 由宿主自行异步化。回调 ctx 经 context.WithoutCancel 处理、保证未取消 (取消/超时终态亦然),回调内可安全执行 IO,需要超时自行派生。 回调无返回值:观察不改变授权结论,回调内部错误由宿主自行处理。
type PolicySource ¶
PolicySource 是外部裁决系统(如风控)在库中的接入点,每次工具调用 被同步咨询。咨询出错时网关按 confirm 判定处理并记录日志(fail-safe: 裁决权威不可达时不静默放行);业务需要 fail-open 时,可在自身实现内 吞掉错误并返回 abstain。咨询位于工具调用的同步关键路径,源应低延迟 或由业务侧缓存。
type ResumeRunner ¶
type ResumeRunner interface {
Run(ctx context.Context, runAgentInput *adapter.RunAgentInput) (<-chan aguievents.Event, error)
}
ResumeRunner 与 AG-UI runner 的运行接口一致,恢复路径用它拉起续跑 运行。aguirunner.New 的返回值直接满足该接口。
type ToolCall ¶
type ToolCall struct {
SessionID string
ToolCallID string
ToolName string
Arguments json.RawMessage
}
ToolCall 是评估与分级看到的调用视图。
type ToolResolver ¶
type ToolResolver func(ctx context.Context) map[string]tool.CallableTool
ToolResolver 在裁决时刻返回"工具名 → 可调用工具"注册表,供恢复路径 代执行使用。做成函数形式使 MCP 等动态工具集可以在决定时刻实时解析。
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package ackhttp 把确认决定/查询路由挂载到任意 http.ServeMux, 仅依赖标准库与 ack。
|
Package ackhttp 把确认决定/查询路由挂载到任意 http.ServeMux, 仅依赖标准库与 ack。 |
|
Package acktest 提供无真实 LLM 时的确定性测试夹具:脚本化模型 (model.Model 实现)与假续跑 runner,供库自身的测试与业务侧的 确认流集成测试使用。
|
Package acktest 提供无真实 LLM 时的确定性测试夹具:脚本化模型 (model.Model 实现)与假续跑 runner,供库自身的测试与业务侧的 确认流集成测试使用。 |
|
examples
|
|
|
notes
command
notes 示例后端入口:基于 trpc-agent-go 的 AG-UI SSE 服务与 ack 许可网关。
|
notes 示例后端入口:基于 trpc-agent-go 的 AG-UI SSE 服务与 ack 许可网关。 |