devonartis/agentwrit
GitHub: devonartis/agentwrit
为 AI 代理提供临时、任务范围的凭证与自动撤销机制,解决静态密钥权限管理难题。
Stars: 1 | Forks: 0
[](https://github.com/devonartis/agentwrit/actions/workflows/ci.yml)
[](https://github.com/devonartis/agentwrit/actions/workflows/codeql.yml)
[](https://securityscorecards.dev/viewer/?uri=github.com/devonartis/agentwrit)
[](https://pkg.go.dev/github.com/devonartis/agentwrit)
[](https://goreportcard.com/report/github.com/devonartis/agentwrit)
[](https://polyformproject.org/licenses/internal-use/1.0.0)
[](https://go.dev/)
[](https://docs.docker.com/compose/)
[](SECURITY.md)
[](https://ed25519.cr.yp.to/)
[](https://spiffe.io/)
## 什么是 AgentWrit?
**AgentWrit 为 AI 代理提供临时的、任务范围的凭证,而不是长期有效的 API 密钥。**
当 AI 代理需要执行某项操作——读取客户记录、调用供应商 API、运行查询——它会向 AgentWrit 经纪人请求一个令牌。该令牌仅适用于该特定任务,几分钟后过期,并且可以在出现异常时在四个不同级别立即撤销。代理永远不会接触到你的长期凭证。
可以将其视为软件发行的法律 **“令状”**:权限有限、时效性、可撤销。
### 为什么这很重要
传统的 IAM 是为人类和长期运行的服务而设计的——而不是为那些启动、执行一个任务然后消失的 AI 代理。代理是短暂的、任务范围的,并且会委托给其他代理。它们需要与生命周期匹配的凭证。AgentWrit 正是为此而设计。
| 传统 AI 代理的 IAM | AgentWrit |
|---|---|
| 代理获取静态 API 密钥或为长期运行服务设计的服务账户凭证 | 每个代理请求一个针对单个任务范围的令牌 |
| 凭证权限过高,因为每任务范围限制是手动且脆弱的 | 范围衰减是自动的——权限不能扩大,只能相等或更窄 |
| 泄露的凭证会暴露服务账户可访问的一切 | 泄露的令牌只暴露一个任务,且已在几分钟内过期 |
| 撤销静态密钥意味着需要在所有使用处轮换 | 撤销在四个级别即时生效——令牌、代理、任务或委托链 |
| 无法查看哪个代理使用了哪个凭证执行哪个任务 | 每个凭证事件都会按代理、任务在不可变哈希链中进行审计 |
| 没有原生的代理到代理委托概念 | 委托内建——代理 A 可以委托范围衰减的令牌给代理 B(相等或更窄),并完整跟踪委托链 |
**想了解完整的安全模型吗?** → [概念与威胁模型](docs/concepts.md)
## 快速开始
**前提条件:** [Docker](https://docs.docker.com/get-docker/)。五分钟获得你的第一个代理令牌。
```
# 设置一个强管理员密钥(broker 缺少它将无法启动)
export AA_ADMIN_SECRET="$(openssl rand -base64 32)"
# 启动 broker
docker run -d --name agentwrit \
-p 8080:8080 \
-e AA_ADMIN_SECRET \
-e AA_BIND_ADDRESS=0.0.0.0 \
-e AA_DB_PATH=/data/data.db \
-e AA_SIGNING_KEY_PATH=/data/signing.key \
-v agentwrit-data:/data \
devonartis/agentwrit:latest
# 确认其已启动
curl -s http://localhost:8080/v1/health | jq .
# 以管理员身份认证
ADMIN_TOKEN=$(curl -s -X POST http://localhost:8080/v1/admin/auth \
-H "Content-Type: application/json" \
-d "{\"secret\":\"$AA_ADMIN_SECRET\"}" | jq -r '.access_token')
# 创建启动令牌(一次性代理注册凭证)
LAUNCH_TOKEN=$(curl -s -X POST http://localhost:8080/v1/admin/launch-tokens \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agent_name": "demo-agent",
"orch_id": "quickstart",
"allowed_scope": ["read:data:*"],
"ttl_seconds": 300
}' | jq -r '.launch_token')
echo "Launch token: ${LAUNCH_TOKEN:0:20}..."
```
你现在拥有一个启动令牌。代理会将其展示一次以注册并获取自己的范围 JWT。
**接下来的步骤:**
| 我希望… | 前往 |
|---|---|
| 使用此启动令牌注册一个代理(Python SDK) | [Python SDK →](docs/python-sdk.md) |
| 查看原始 HTTP 注册流程(curl + openssl) | [入门指南 →](docs/getting-started-user.md) |
| 从源码构建或改用 Docker Compose | [其他安装选项 →](#other-install-options) |
| 理解刚刚发生的事情(认证模型、SPIFFE ID、范围) | [概念 →](docs/concepts.md) |
## 它是如何工作的
AgentWrit 实现了 [临时代理凭证 v1.3](https://github.com/devonartis/AI-Security-Blueprints/blob/main/patterns/ephemeral-agent-credentialing/versions/v1.3.md) 安全模式——一个为自治 AI 代理量身打造的 8 组件架构。该模式是 [AI 安全蓝图](https://github.com/devonartis/AI-Security-Blueprints) 项目的一部分,而 AgentWrit 是其参考实现。
1. **Operator** 创建具有允许范围上限的启动令牌
2. **App** 将启动令牌交给代理以执行特定任务
3. **Agent** 使用 Ed25519 挑战-响应向经纪人注册,获取短期 JWT
4. **Agent** 使用 JWT 作为承载令牌访问资源服务器
5. **Agent** 完成任务后释放令牌——或经纪人可在四个级别撤销它
**10 个组件,一个二进制文件。** 经纪人处理身份、令牌、范围、撤销、委托、审计、应用管理、管理员认证、可观测性与持久化——全部在一个 Go 二进制文件中,仅有 5 个直接依赖。
| 组件 | 作用 | 包路径 |
|-----------|-------------|---------|
| 身份 | 挑战-响应注册、SPIFFE ID | [`internal/identity`](internal/identity) |
| 令牌 | EdDSA JWT 发行/验证/续期,最大 TTL 上限 | [`internal/token`](internal/token) |
| 授权 | 对每个受保护路由进行范围强制 | [`internal/authz`](internal/authz) |
| 撤销 | 4 级撤销:令牌、代理、任务、链 | [`internal/revoke`](internal/revoke) |
| 审计 | 不可变哈希链事件日志 | [`internal/audit`](internal/audit) |
| 委托 | 范围衰减的子令牌 | [`internal/deleg`](internal/deleg) |
| 应用 | 应用注册与客户端凭证 | [`internal/app`](internal/app) |
| 管理员 | 管理员认证(bcrypt)、启动令牌 | [`internal/admin`](internal/admin) |
| 可观测性 | 结构化日志、Prometheus `/v1/metrics` | [`internal/obs`](internal/obs) |
| 存储 | SQLite 持久化 | [`internal/store`](internal/store) |
**深入探索:** [架构图与数据流 →](docs/architecture.md)
## 实际演示 —— MedAssist AI 示例
Python SDK 包含 **MedAssist AI**:一个 FastAPI Web 应用,本地 LLM 动态创建带有每患者范围凭证的经纪人代理。你可以看到范围强制、跨患者拒绝、委托与审计——全部在实时跟踪中呈现。
| 你将看到 | 它证明了什么 |
|---|---|
| 代理按 LLM 工具调用按需生成 | 动态代理创建有效 |
| 每个代理范围限定到一个患者 ID | 每资源范围隔离 |
| LLM 请求错误患者 → `scope_denied` | 范围强制拦截越界访问 |
| 临床代理委托给处方代理 | 范围衰减的委托 |
| 令牌在交互期间续期并释放 | 完整生命周期管理 |
**运行它:** [MedAssist AI 示例 →](docs/demos.md) · [新手引导 →](docs/demos.md) · [演示者指南 →](docs/demos.md)
## SDK
| 语言 | 仓库 | 安装 | 状态 |
|----------|------|---------|--------|
| **Python** | [agentwrit-python](docs/python-sdk.md) | `pip install agentauth` *(PyPI 重命名待定)* | v0.3.0 — 15 个验收测试通过 |
| **TypeScript** | 即将推出 | — | 计划中 |
```
from agentauth import AgentAuthApp
# SDK 隐藏了 Ed25519 挑战-响应流程
agent = AgentAuthApp(broker_url="http://localhost:8080").register(
launch_token=LAUNCH_TOKEN,
task_id="read-customer-42",
requested_scope=["read:data:customers:42"],
)
# 在资源服务器上使用令牌
response = httpx.get(url, headers=agent.bearer_header)
# 完成 — 释放凭证
agent.release()
```
**完整 SDK 文档:** [Python SDK →](docs/python-sdk.md)
## API 概览
19 个端点。完整模式与示例请参考 [API 参考 →](docs/api.md)。
| | 方法 | 路径 | 使用方 |
|---|---|---|---|
| **公开** | `GET` | `/v1/` | 任何人 — 健康检查 |
| | `GET` | `/v1/metrics` | 监控 — Prometheus |
| | `GET` | `/v1/challenge` | 代理 — 获取注册随机数 |
| | `POST` | `/v1/token/validate` | 资源服务器 — 验证令牌 |
| **认证** | `POST` | `/v1/admin/auth` | Operator — 获取管理员 JWT |
| | `POST` | `/v1/app/auth` | 应用 — 客户端凭证交换 |
| | `POST` | `/v1/register` | 代理 — 使用启动令牌注册 |
| **令牌** | `POST` | `/v1/token/renew` | 代理/应用 — 到期前续期 |
| | `POST` | `/v1/token/release` | 代理 — 信号任务完成 |
| | `POST` | `/v1/delegate` | 代理/应用 — 范围衰减子令牌 |
| **管理员** | `POST` | `/v1/admin/launch-tokens` | Operator — 创建代理启动令牌 |
| | `POST` | `/v1/applications` | Operator — 注册应用 |
| | `GET` | `/v1/applications` | Operator — 列出应用 |
| | `GET` | `/v1/applications/{id}` | Operator — 获取应用详情 |
| | `PUT` | `/v1/applications/{id}` | Operator — 更新应用范围/TTL |
| | `DELETE` | `/v1/applications/{id}` | Operator — 注销应用 |
| | `POST` | `/v1/revoke` | Operator — 在 4 个级别撤销 |
| | `GET` | `/v1/audit/events` | Operator — 查询审计追踪 |
所有错误均返回 [RFC 7807](https://tools.ietf.org/html/rfc7807) `application/problem+json`。
## 其他安装选项
### Docker Compose(本地克隆并构建)
```
git clone https://github.com/devonartis/agentwrit.git && cd agentwrit
export AA_ADMIN_SECRET="$(openssl rand -base64 32)"
./scripts/stack_up.sh
curl -s http://localhost:8080/v1/health | jq .
```
拆除:`./scripts/stack_down.sh`
### 从源码构建(Go 1.24+)
```
go build -o bin/broker ./cmd/broker/
go build -o bin/awrit ./cmd/awrit/
./bin/awrit init --config-path /tmp/agentwrit/config
AA_CONFIG_PATH=/tmp/agentwrit/config ./bin/broker
```
### 预构建 Docker 镜像标签
| 标签 | 是否变动 | 用途 |
|---|---|---|
| `v2.0.0` | 否 | **生产环境** — 固定语义化版本 |
| `main-` | 否 | 可重现部署 — 固定到特定提交 |
| `latest` | 每次 `main` 推送时更新 | 仅限实验室与评估 |
**验证镜像(可选,推荐):**
```
cosign verify devonartis/agentwrit:latest \
--certificate-identity-regexp='^https://github.com/devonartis/agentwrit/\.github/workflows/release\.yml@' \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com
```
## 配置
所有环境变量使用 `AA_` 前缀。仅 `AA_ADMIN_SECRET` 为必需——没有它经纪人将退出。
| 变量 | 默认值 | 作用 |
|----------|---------|-------------|
| `AA_ADMIN_SECRET` | *(必需)* | 根凭证——请像对待根密码一样对待 |
| `AA_PORT` | `8080` | HTTP 监听端口 |
| `AA_BIND_ADDRESS` | `127.0.0.1` | 绑定地址(Docker 中使用 `0.0.0.0`) |
| `AA_DEFAULT_TTL` | `300` | 令牌生命周期(秒,5 分钟) |
| `AA_MAX_TTL` | `86400` | 令牌生命周期上限(24 小时) |
| `AA_DB_PATH` | `./data.db` | SQLite 数据库路径 |
| `AA_SIGNING_KEY_PATH` | `./signing.key` | Ed25519 密钥路径(自动生成) |
| `AA_TLS_MODE` | `none` | `none`、`tls` 或 `mtls` |
| `AA_LOG_LEVEL` | `verbose` | `quiet`、`standard`、`verbose`、`trace` |
**完整配置参考**(所有环境变量、TLS/MTLS 设置、配置文件、操作员 CLI):[操作员指南 →](docs/getting-started-operator.md)
## 操作员 CLI(`awrit`)
```
go build -o bin/awrit ./cmd/awrit/
export AACTL_BROKER_URL=http://localhost:8080
export AACTL_ADMIN_SECRET="your-secret"
awrit init # Generate broker config
awrit app register --name my-pipeline --scopes "read:data:*" # Register an app
awrit revoke --level agent --target # Revoke all agent tokens
awrit audit events --outcome denied --limit 20 # Query audit trail
```
**完整 CLI 参考:** [awrit 命令与标志 →](docs/awrit-reference.md)
## 运行测试
```
go test ./... # All tests
go test ./... -short # Unit tests only
./scripts/gates.sh task # Build + lint + unit + security scan
./scripts/gates.sh module # Full gates including Docker E2E
```
## 文档
| 我希望… | 前往 |
|---|---|
| 从零开始入门 | [快速入门 →](docs/getting-started-user.md) |
| 将应用与经纪人集成 | [开发者指南 →](docs/getting-started-developer.md) |
| 部署与操作经纪人 | [操作员指南 →](docs/getting-started-operator.md) |
| 查看所有 API 端点与模式 | [API 参考 →](docs/api.md) |
| 理解安全模型 | [概念与威胁模型 →](docs/concepts.md) |
| 查看架构图 | [架构 →](docs/architecture.md) |
| 遵循常见工作流 | [常见任务 →](docs/common-tasks.md) |
| 调试问题 | [故障排除 →](docs/troubleshooting.md) |
| 查看真实集成模式 | [集成模式 →](docs/integration-patterns.md) |
| 使用 Python SDK | [Python SDK →](docs/python-sdk.md) |
| 运行 MedAssist 示例 | [MedAssist AI →](docs/demos.md) |
| 阅读常见问题 | [FAQ →](docs/faq.md) |
| 报告安全漏洞 | [安全策略 →](SECURITY.md) |
| 阅读变更日志 | [变更日志 →](CHANGELOG.md) |
## 许可证
AgentWrit 根据 **[PolyForm Internal Use License 1.0.0](https://polyformproject.org/licenses/internal-use/1.0.0)** 授权——一种面向内部业务使用的源可用许可证。
**免费供任何人内部使用,包括盈利公司。** 任何个人、企业或组织均可将 AgentWrit 用于自身内部运营,无需联系许可方且免费。这包括受委托方代表被许可用户进行的修改。面向盈利公司的内部业务使用明确允许。
**需要商业许可的情况:**
- 托管或管理的 SaaS 服务向第三方提供——付费或免费
- 将 AgentWrit 嵌入你销售或再分发的产品中
- 转售或再分发 AgentWrit 或其修改版本
- 任何第三方访问正在运行的 AgentWrit 实例,包括跨组织共享安装
**双许可联系人:** 非商业和研究用途(高校、教育、辅导计划、开源项目、行业团体)通常可免费申请。商业嵌入、转售和托管服务需要付费商业许可。请发送邮件至 **licensing@agentwrit.com** 说明您的使用场景。
请参阅 [LICENSE](LICENSE) 获取完整许可文本。
## 使用的技术
基于 [Claude](https://claude.ai) 由 [Anthropic](https://anthropic.com) 协助构建
标签:AI代理, API安全, Docker, EdDSA, EVTX分析, Go语言, JSONLines, JSON输出, SPIFFE, XML 请求, 临时令牌, 代码分析, 任务范围令牌, 内部使用, 凭证管理, 可撤销令牌, 安全令牌服务, 安全开发, 安全徽章, 安全策略, 安全评分, 安全防御评估, 密钥轮换, 工作流自动化, 开源, 授权, 提示词设计, 日志审计, 最小权限, 版权保护, 短期凭证, 程序破解, 自动吊销, 自定义请求头, 身份代理, 零信任