关于 tidebase
Tidebase 为 AI Agent 提供身份、凭据代理,以及运行检查点、队列、计划和审批门,并将持久数据存储在自有 Postgres 中。它不运行应用代码,而是让现有运行时管理恢复、审计和敏感凭据。
主要功能
- 01为 Agent 隔离身份并代理凭据
- 02持久化运行检查点与状态
- 03支持队列、计划和失败恢复
- 04设置可持久化的审批门
- 05在自有 Postgres 中存储数据
适用场景
- 01不向模型暴露密钥地调用外部 API
- 02从失败步骤恢复 Agent 运行
- 03在高风险操作前请求人工审批
- 04通过 Studio 检查运行与审批状态
MCP 相关
可通过 @tidebase/mcp 向 AI 助手提供运行、审批门与恢复操作。示例 MCP 网关还能将其他 MCP 服务的工具调用包装为带检查点的操作。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
7收录的工具列表 · 更新于 2 周前
此工具无需参数。
详细介绍
Tidebase
为 AI Agent 提供身份验证和凭证代理,并支持检查点、队列、计划任务和审批关卡。数据存储在你自己的 Postgres 中。

Tidebase 为你的 AI Agent 提供身份和保险库。当 Agent 调用 API 时,请求会经过 Tidebase,由它注入凭证,因此 Agent 和模型都看不到密钥。你可以限定其范围、审计使用情况并撤销凭证。
Tidebase 还会保存持久化数据:检查点、实时状态、队列、计划任务和审批关卡,全部存储在你自己的 Postgres 中。代码仍在你的应用、工作进程或作业进程中运行;Tidebase 不会运行代码。因此,“这次运行在第 7 步失败了,重新运行安全吗?”这个问题有了答案,而“Agent 以明文形式持有我的 GitHub 令牌”也不再成立。
文档:https://tidebase.dev · 社区:Discord · 面向 AI 助手:/llms.txt
为什么选择 Tidebase
Agent 产品通常会逐渐需要相同的运维基础设施:
- 为每个 Agent 分配独立身份,而不是共用一个 API 密钥
- 用于存放第三方密钥和 OAuth 令牌的保险库
- 在不把密钥交给模型的情况下调用 API
- 用于记录运行和步骤状态的表
- 用于保存部分进度的检查点数据
- 重试标记和人工审核状态
- 向界面实时推送进度
- 针对高风险操作的审批关卡
- 令牌和成本台账
- 用于恢复和外部审核界面的 Webhook 连接逻辑
Tidebase 将这一层封装起来,围绕你现有的代码提供服务,并通过凭证代理,让 Agent 在不持有密钥的情况下操作实际服务。它不会运行你的代码(运行环境仍由你掌控),也不是大模型代理或托管式工作进程运行环境。
快速开始
最快的方式(无需 Node),使用预构建的服务端镜像:
docker compose --profile server up -d # Postgres + ghcr.io/blueprintlabio/tidebase on :7373
然后让任意 SDK 连接到 http://localhost:7373(npm i @tidebase/sdk 或 pip install tidebase)。
开发环境设置(从源代码运行服务端和 Studio):
启动 Postgres:
docker compose up -d postgres
安装依赖:
pnpm install
运行服务端和 Studio:
pnpm dev
- 服务端:http://localhost:7373
- Studio:http://localhost:5173
运行示例工作流:
pnpm example
在完成两个检查点后强制失败:
FAIL_WRITE=1 pnpm example
从 Studio 或 API 复制运行 ID,然后恢复运行:
TIDEBASE_RUN_ID=run_xxx pnpm example
plan 和 fetch-sources 步骤会从检查点恢复。只有 write-report 会重新执行。
为 Agent 提供独立身份,将第三方密钥存入保险库,让 Agent 无需持有密钥即可调用 API。Tidebase 会注入密钥并发起出站调用,你可以限定范围、审计并撤销授权。
import { Tidebase } from '@tidebase/sdk'
const tide = new Tidebase({ baseUrl: 'http://localhost:7373', apiKey: process.env.TIDEBASE_API_KEY })
// 1. Vault a secret behind a pinned upstream. The returned resource never carries the secret.
await tide.resources.connect('github', {
provider: 'static',
baseUrl: 'https://api.github.com',
secret: process.env.GITHUB_TOKEN,
scopesAllowed: ['repo.read'],
})
// 2. Inside a run, request a grant for what the agent needs to do.
const auth = tide.auth(runId)
const grant = await auth.request({
resource: 'github:repo:acme/app',
action: 'repo.read',
scopes: ['repo.read'],
})
// 3. Make the call through Tidebase. The token is injected upstream; the agent and the LLM never see it.
const res = await auth.use(grant.grantId, { method: 'GET', path: '/user' })
密钥在静态存储时使用信封加密(AES-256-GCM,并由 KMS 包装 DEK)。baseUrl 将上游地址固定,scopesAllowed 限制任何授权的范围,因此即使授权泄露,也无法访问任意主机。代理会屏蔽私有 IP 和元数据主机(防御 SSRF),而 GET /audit 返回的授权凭据中不含任何密钥材料。对于 OAuth 提供商,你可以将凭据托管委托给 nango 或 openbao,Tidebase 只保留不透明的连接引用。
在 AI 编码 Agent 中使用 Tidebase
让项目中的每个 AI 会话都正确使用 Tidebase:
npx @tidebase/sdk init # writes a Tidebase section into AGENTS.md/CLAUDE.md (idempotent)
通过 MCP 让助手直接访问运行、关卡和恢复功能:
claude mcp add tidebase -e TIDEBASE_URL=http://localhost:7373 -- npx -y @tidebase/mcp
或者安装 Claude Code 插件(包含技能和 MCP 服务):
/plugin marketplace add BlueprintLabIO/tidebase
/plugin install tidebase@tidebase
面向 Agent 的文档位于 tidebase.dev/llms.txt;每个文档页面也都提供对应的原始 .md 文件。
队列、计划任务与取消(v0.5)
Tidebase 现在可以决定代码何时运行,同时仍绝不执行代码:
// durable queue: dedupe, delay, retries with backoff, concurrency caps
await tide.enqueue('generate-report', {
queue: 'reports',
input: { topic },
dedupeKey: `report:${topic}`,
maxAttempts: 3,
deadlineMs: 600_000
})
// pull-mode worker: claims ready runs and executes registered workflows
tide.workflow('generate-report', generateReport)
await tide.work({ queues: ['reports'] })
// cron (UTC, 5-field), double-fires are structurally impossible
await tide.schedules.set('daily-digest', {
cron: '0 9 * * *',
workflowName: 'daily-digest'
})
// authoritative, one-way cancellation, workers observe it at step/gate
// boundaries; complete/fail can never resurrect a cancelled run
await tide.runs.cancel(runId, { reason: 'customer asked', actor: 'support' })
现在也支持推送模式分发:为队列配置 invokeUrl 后,Tidebase 会向你的应用发送签名的 run.invoke Webhook,而不是等待领取。排队的任务就是一次运行,queued 是生命周期状态,而不是第二张表,因此状态永远不会不一致。
完整生命周期、重放约定、工作进程退出后的恢复模型以及部署规范(通过 pnpm migrate 执行版本化迁移,扩展/收缩部署时设置 TIDEBASE_AUTO_MIGRATE=0),请参阅 docs/production.md。
测试
pnpm test
测试套件(84 个 TypeScript 测试 + 9 个 Python 集成测试,在 CI 中每次推送时运行)使用同一个 Postgres,并在隔离的 tidebase_test 数据库中执行。它以不变量为驱动,而非以覆盖率为驱动:每项测试都会通过公共 API 或 SDK,针对真实 Postgres,验证持久性或安全保证;还包括并发探测,以验证仅在争用时才会显现的保证。
测试验证的内容:
- 已完成的步骤会从存储中重放,绝不会重新执行,包括崩溃后通过恢复 Webhook 恢复的情况
- 步骤租约与运行租约互斥且带有围栏机制,僵尸工作进程无法写入过时结果
- 重放时会在输入哈希漂移导致运行数据损坏前拒绝请求
- 故障分类遵循恢复约定:未设置幂等键的外部写入会进入
manual_review,设置了幂等键的步骤和只读步骤则属于safe_replay - 并发写入时,每次运行的事件日志都无间隙且严格有序
- 每个关卡只会解析一次,且必须提供解析令牌;恢复时会重放其决策
- 子运行以边名称作为幂等依据,因此恢复后的扇出会复用现有子运行
- 恢复 Webhook 和渠道投递都带有 HMAC 签名;SDK 会拒绝未签名、被篡改或伪造的载荷
- 渠道端点响应缓慢或挂起,绝不会阻塞对该运行的其他写入
完整的不变量映射和约定请参阅 docs/testing.md。
API 结构
import { Tidebase } from '@tidebase/sdk'
const tide = new Tidebase()
await tide.run('generate-report', { runId }, async (run, input) => {
const plan = await run.step('plan', () => makePlan(input))
await run.state.set({
status: 'writing',
progress: 0.7
})
return run.step('write-report', () => writeReport(plan))
})
会话运行
tide.run() 适用于函数式的工作。对于开放式执行、位于 Agent 前面的协议网关、REPL 或跨多个请求的运行,可以改为将运行附加到会话:
const session = await tide.runs.attach('mcp-session', { input: { agent: 'hermes' } })
// session is a RunContext: step/gate/state/usage/snapshots all work unchanged
await session.step('tool-call', { input: args }, () => callTool(args))
await session.complete({ calls: 12 }) // or session.fail(err)
会话通过后台心跳(heartbeatMs,默认 20s)持有运行租约。如果进程退出,心跳会停止,租约到期,协调器便会接管,执行重新入队或恢复 Webhook,就像工作流工作进程崩溃时一样。丢失租约(onLeaseLost)的会话会变成僵尸:服务端会隔离其写入。传入 runId 可恢复现有会话的运行;已完成的步骤会从存储中重放。
如需完整的示例,了解如何通过更改一行配置,将任意 Agent 的 MCP 服务封装到 MCP 网关中,实现带检查点的工具调用和持久化审批关卡,请参阅 examples/mcp-gateway/。
恢复契约
每个步骤都可以声明 Tidebase 应记录以供重放的运行契约:
await run.step(
'send-email',
{
input: { userId },
sideEffects: ['email.send'],
idempotencyKey: `welcome:${userId}`,
replay: 'auto',
checkpointInvariant: 'provider accepted the message id',
verifiedBy: 'email provider response'
},
() => sendWelcomeEmail(userId)
)
Tidebase 会将该契约与步骤一同记录,并在 Studio 中显示。最终步骤失败会分类为:
- 如果仍有 SDK 重试次数,则为
failed_retryable。 - 如果需要手动重放,或存在副作用但没有幂等键,则为
manual_review。 - 硬性失败则为
failed。
这不会让外部系统实现恰好一次。它会明确恢复决策,而不是将其隐藏在日志和自定义重试标记中。
版本化状态与快照
run.state.set() 和 run.state.patch() 仍会更新当前运行状态。在 v0.2 中,它们还会将一个版本追加到 Tidebase 的状态历史中。
await run.state.patch({
status: 'writing',
progress: 0.7
})
当当前状态成为有意义的审查点或还原点时,可以为其添加标签:
await run.state.save('before-approval', {
reason: 'the user is about to approve sending'
})
快照是基于带标签状态版本的便捷 API,适用于报告、工件、工作区、文档或应用状态等外部目标:
await run.snapshots.create('draft-v1', {
target: { type: 'report', id: reportId },
state: draft,
reason: 'first complete draft'
})
该模型刻意保持精简:
current state = latest version in a stream
snapshot = labeled state version
time travel = read an older version
fork = create new app/run context from an older version
restore = append a new version based on an older version
Tidebase 会存储并公开这些版本。如何还原或分叉自己的状态目标,由你的应用决定。
子运行与扇出
较长的 Agent 工作流通常会扇出到多个子 Agent,并汇总它们的结果。Tidebase v0.2 通过父子运行关系边和带检查点的汇总步骤来实现这一模式。
const results = await run.fanout('research-options', [
{
name: 'flights',
workflow: researchFlights,
input: { destination }
},
{
name: 'hotels',
workflow: researchHotels,
input: { destination }
},
{
name: 'food',
workflow: researchFood,
input: { destination }
}
])
子运行的创建以父运行和边名称为依据,具有幂等性。如果父运行恢复,Tidebase 会返回现有子运行,而不是创建重复项。汇总结果会存储在名为 join:<fanout-name> 的常规带检查点步骤中。
关卡与通道
通道会将 Tidebase 事件传递到外部界面。Alpha 版本支持 Webhook 通道:
await tide.run(
'generate-report',
{
input: { topic: 'channels' },
channels: [{
type: 'webhook',
url: 'https://your-app.example.com/api/tidebase-events',
events: ['run.failed', 'step.failed', 'gate.created']
}]
},
workflow
)
关卡会创建持久化审批决策,可由 Studio、产品 UI、Slack/Teams 适配器、内部工具或本地审查页面解决:
const decision = await run.gate('approve-send', {
prompt: 'Send this report to the customer?',
data: { reportId },
channels: [{ type: 'webhook', url: process.env.REVIEW_WEBHOOK_URL! }],
capability: {
name: 'report.send',
scopes: ['report:send'],
reason: 'agent wants to send an external report'
}
})
if (decision.decision !== 'approved') {
throw new Error('Report was not approved')
}
Webhook 关卡载荷包含 resolveUrl 和 resolveToken,供审查者解决关卡。(凭据由 Broker 单独处理;请参阅 Agent 身份验证部分。)
当你无法等待人工审批时,例如在 HTTP 处理器、机器人或协议网关中,可以使用 run.gate() 所基于的非阻塞拆分模式:
const gate = await run.gates.begin('approve-send', { prompt: 'Send it?', data: { reportId } })
if (gate.status === 'pending') {
// return now; check back with run.gates.get(gate.gateId) on a later request
}
在一次运行中,关卡开始操作按名称实现幂等:重新开始已解决的关卡会立即返回其决策,因此重试的调用方最终会得到同一个答案。
运行本地审批通道:
pnpm example:review
在另一个终端中:
REQUIRE_APPROVAL=1 \
TIDEBASE_CHANNEL_WEBHOOK=http://localhost:8788/tidebase-events \
pnpm example
打开 http://localhost:8788,批准该关卡,工作流便会继续。
恢复 Webhook
当一次运行失败且配置了恢复 Webhook 时,Tidebase 可以回调你的应用。SDK 可以处理该 Webhook 并恢复匹配的工作流。
const run = await tide.runs.create('generate-report', {
input: { topic: 'checkpoints' },
recoveryWebhook: 'https://your-app.example.com/api/tidebase'
})
Tidebase 会记录每次恢复尝试的投递状态、HTTP 状态、响应正文和错误。如果服务器和 SDK 都设置了 TIDEBASE_WEBHOOK_SECRET,恢复负载会使用 x-tidebase-signature 签名。
示例包含一个本地 Webhook 服务器:
pnpm example:webhook
用量跟踪
Tidebase 可以记录一次运行的通用资源用量,而无需代理模型或提供商调用:
await run.usage.record({
kind: 'llm',
provider: 'openai',
model: 'gpt-4.1-mini',
label: 'draft-response',
inputTokens: 1200,
outputTokens: 420,
costUsd: 0.012
})
用量记录会与运行一同存储,作为 usage.recorded 事件发出,并在 Studio 中汇总。同一台账也可以跟踪非 LLM 资源:
await run.usage.record({
kind: 'tool',
provider: 'internal-search',
quantity: 8,
unit: 'queries',
costUsd: 0.004
})
Tidebase 存储的内容
- 运行和尝试
- 命名的检查点步骤
- 防止重复使用过期检查点的输入哈希
- 步骤恢复契约
- 实时运行状态
- 版本化状态流
- 带标签的状态版本和快照
- 父子运行关系
- 仅追加的运行事件
- 恢复尝试
- Webhook 通道投递记录
- 持久化门控和决策
- 凭据/能力审计元数据
- 用于跟踪令牌、单位和成本的通用用量记录
所有数据都由 Postgres 提供支持,并且从第一天起就为可自托管而设计。
当前范围
- 由 Postgres 提供支持的运行存储
- 权威运行生命周期,原生支持取消和截止时间
- 持久化队列(去重、延迟、优先级、重试/退避、并发和速率上限)
- Cron 调度(UTC、防止重复触发)
- 拉取模式 Worker(
tide.work)和推送模式签名调用 Webhook - 调谐器(租约过期后重新入队/恢复、截止时间取消、Cron、派发)
- 版本化迁移运行器
- TypeScript SDK
- Python SDK,包含 asyncio(
sdk-python/、tidebase.aio) - SvelteKit Studio
- 实时状态设置/补丁
- 状态历史记录和带标签的快照
- 子运行和扇出汇合
- SSE 事件流
- 签名恢复 Webhook
- Webhook 通道
- 持久化门控
- 用量/资源台账
- Dogfood 工作流
- Agent 身份验证 + 凭据代理:每个 Agent 使用密钥对标识、绑定运行的授权、用于存储机密并将其注入代理调用的保险库(客户端和 LLM 都无法看到这些机密)、策略引擎、SSRF 防御,以及 Nango/OpenBao 后端
Alpha 版本不包含的内容
截至 v0.7.0(2026 年 6 月)。更早的 Alpha 版本曾将队列、调度、取消、审批门控、API 身份验证和凭据代理列在此处。这些功能都已发布(v0.5 至 v0.7):支持重试/退避的持久化队列、Cron、权威取消、恰好一次门控、会话运行、可选的 Bearer 身份验证、可检测已死亡 Worker 并重新派发任务的调谐器,以及 v0.7 中的 Agent 身份验证控制平面和凭据代理。以下内容仍被刻意排除在范围之外:
- Tidebase 托管的代码执行(你的运行时仍由你掌控;这是永久不支持的功能,并非待开发)
- LLM 网关/代理
- 托管的通道适配器
- Agent 记忆(对话或嵌入存储)
- 多租户身份验证(目前使用单个共享 API 密钥)
- 托管云服务
Alpha 版本说明
此版本适合本地演示和早期反馈,不适用于生产环境。
重要限制:
- 迁移已进行版本管理并使用咨询锁;开发环境会在启动时自动迁移,设置
TIDEBASE_AUTO_MIGRATE=0并运行pnpm migrate,即可遵循扩展/收缩部署规范。 - API 身份验证默认关闭:在服务器和 SDK 中设置
TIDEBASE_API_KEY(Studio 中设置VITE_TIDEBASE_API_KEY)即可启用。未设置时,API 处于开放状态,只能在可信的本地/自托管环境中使用。 - 外部副作用仍需在用户代码中使用幂等键。
- Tidebase 会记住发生过的事情,并可以调用恢复 Webhook,但不保证用户代码届时仍可用来恢复。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。