首页
/ Scientific Agent Skills 之 Adaptyv 技能:用 Foundry API 打通蛋白实验从序列提交到数据回传的全链路

Scientific Agent Skills 之 Adaptyv 技能:用 Foundry API 打通蛋白实验从序列提交到数据回传的全链路

2026-09-05 21:01:55作者:郜逊炳

本篇基于 Scientific Agent Skills 仓库中的 skills/adaptyv 技能,完整讲解 Adaptyv Bio 云实验室(Foundry)API 的接入方式:如何完成认证与 SDK 安装,如何用装饰器或 FoundryClient 提交蛋白结合/热稳定性/表达/荧光实验,如何跟踪九段式实验生命周期并拉回动力学与 Tm 数据。读完后你可以让 AI Agent 直接编写可运行的 Foundry 集成代码,把"提交氨基酸序列 → 自动实验室检测 → 结构化结果回传"的约 21 天实验闭环变成几行 Python。

Adaptyv FoundryClient 工作流示意图:左上为 targets 目录与多链 sequences 输入及 cost_estimate 报价,右上为 Draft 起步的实验生命周期与 BLI 检测板,下方为 get_results 返回的 BLI sensorgram、KD/kon/koff 动力学参数表和 Tm 熔解曲线

技能定位:它教 Agent 做什么

Adaptyv Bio 是一个云实验室:用户通过 API 或 Web 界面提交氨基酸序列,其自动化实验室执行结合(BLI/SPR)、热稳定性、表达与荧光等检测,并在约 21 天内回传实验数据(原文表述,见 skills/adaptyv/SKILL.md 第 13 行)。在仓库的 README 中,它被归入"Protein Engineering & Design"类别,定位为"Cloud laboratory platform: Adaptyv (automated protein testing and validation)"。

该技能的触发条件写在 frontmatter 的 description 中:当用户提到 Adaptyv、Foundry API、蛋白结合实验、蛋白筛选、BLI/SPR 检测、热稳定性检测,或代码中 import 了 adaptyvadaptyv_sdkFoundryClient,或引用了 foundry-api-public.adaptyvbio.com 时,Agent 应启用本技能。

适用前提(来自 frontmatter compatibility 字段):

  • Python 3.10+;
  • 拥有一个 Adaptyv Foundry 账号,以及从 Foundry 门户侧边栏获取的 API key;
  • 通过 uv 从 GitHub 安装 adaptyv-sdk(0.1.0 beta,尚未发布到 PyPI)。

需要说明的是,从目录结构看,skills/adaptyv/ 不包含 scripts/ 目录,是一个纯文档型参考技能:仓库安全扫描报告 docs/security-report.md 也将其标注为"documentation-only reference for the Adaptyv Bio Foundry API"。它的全部价值在于把 Foundry API 的认证约定、实验生命周期和 32 个端点的请求/响应契约固化成 Agent 可执行的集成知识。

认证与 API 基础约定

  • Base URLhttps://foundry-api-public.adaptyvbio.com/api/v1
  • 认证方式Authorization 请求头携带 Bearer token;token 从 Foundry 门户(foundry.adaptyvbio.com)侧边栏获取。
  • 密钥来源:写代码时一律从环境变量 ADAPTYV_API_KEY 或项目根目录的 .env 文件读取密钥——绝不硬编码 token。技能给出的实操建议是:先检查项目根目录是否存在 .env 文件,若存在则用 python-dotenv 之类的库加载它。
  • 变量名约定:官方文档的 curl 示例使用 FOUNDRY_API_TOKEN,它与本技能推荐的 ADAPTYV_API_KEY 是同一个 Bearer token;为了与 SDK 保持一致,Python 代码和新写的 shell 脚本应统一采用 ADAPTYV_API_KEY

最小可用验证请求(除 GET /openapi.json 外,其余所有请求都需要认证):

export ADAPTYV_API_KEY="abs0_..."
curl https://foundry-api-public.adaptyvbio.com/api/v1/targets?limit=3 \
  -H "Authorization: Bearer $ADAPTYV_API_KEY"

技能同时强调:token 只能存放在环境变量或 .env 文件中,绝不能提交到版本控制系统。GET /openapi.json 端点无需认证,可用于机器读取完整的 OpenAPI 规范。

安装 Python SDK 与环境变量

adaptyv-sdk 目前是 0.1.0 beta,未上 PyPI,需要从 GitHub 安装:

uv pip install "git+https://github.com/adaptyvbio/adaptyv-sdk.git"

在带 pyproject.toml 的项目里则用:

uv add "adaptyv-sdk @ git+https://github.com/adaptyvbio/adaptyv-sdk.git"

SDK 相关环境变量(设在 shell 或 .env 文件中):

变量 必填 说明
ADAPTYV_API_KEY Foundry Bearer token
ADAPTYV_API_URL 默认 https://foundry-api-public.adaptyvbio.com/api/v1
ADAPTYV_ORGANIZATION_ID 组织 ID

@lab.experiment 装饰器与 FoundryClient 在显式传参之外,都会自动从环境中读取 ADAPTYV_API_KEYADAPTYV_API_URL,因此多数场景下显式传参可以省略。

供应链与安全提示:仓库的安全扫描(docs/security-report.md 中 adaptyv 条目,评级 MEDIUM)指出,上述安装命令直接拉取 SDK 仓库 HEAD 的代码,未固定 commit、tag 或版本,且 0.1.0 未发布到 PyPI,缺少注册表级别的原生完整性校验。报告的整改建议是:把安装固定到具体 tag 或 commit SHA(如 git+https://github.com/adaptyvbio/adaptyv-sdk.git@<commit-sha>),并在从源码仓库安装包前征得用户确认。此外扫描报告还提示,下文"自动化流水线"工作流中的 skip_draft + auto_accept_quote 组合会在无人工审核的情况下直接创建真实发票,生产环境使用需格外谨慎。

两种编程模式

装饰器模式:最少的样板代码

装饰器负责实验提交,返回对象带 experiment_url 可直接跳转到 Foundry 门户(代码见 skills/adaptyv/SKILL.md#L61-L70):

from adaptyv import lab

@lab.experiment(target="PD-L1", experiment_type="screening", method="bli")
def design_binders():
    return {"design_a": "MVKVGVNG...", "design_b": "MKVLVAG..."}

result = design_binders()
print(f"Experiment: {result.experiment_url}")

适合"定义一批序列 → 一次性提交"的脚本化场景,target、实验类型、方法都收敛在装饰器参数里。

客户端模式:完整的生命周期控制

需要浏览目录、估价、创建、提交、回取结果时,使用 FoundryClient(代码见 skills/adaptyv/SKILL.md#L74-L106):

import os
from adaptyv import FoundryClient

client = FoundryClient(
    api_key=os.environ["ADAPTYV_API_KEY"],
    base_url=os.environ.get(
        "ADAPTYV_API_URL",
        "https://foundry-api-public.adaptyvbio.com/api/v1",
    ),
)

# Browse targets
targets = client.targets.list(search="EGFR", selfservice_only=True)

# Estimate cost
estimate = client.experiments.cost_estimate({
    "experiment_spec": {
        "experiment_type": "screening",
        "method": "bli",
        "target_id": "target-uuid",
        "sequences": {"seq1": "EVQLVESGGGLVQ..."},
        "n_replicates": 3
    }
})

# Create and submit
exp = client.experiments.create({...})
client.experiments.submit(exp.experiment_id)

# Later: retrieve results
results = client.experiments.get_results(exp.experiment_id)

客户端命名空间与端点分组一一对应:client.targetsclient.experiments,底层映射到参考文档中的 Experiments / Targets 等端点族。

实验类型与字段要求

五种实验类型及其检测方法(继承自 skills/adaptyv/SKILL.md#L110-L116):

类型 方法 测量内容 需要 Target
affinity blispr KD、kon、koff 动力学
screening blispr 结合与否(是/否)
thermostability 熔解温度(Tm)
expression 表达量
fluorescence 荧光强度

创建实验的 POST /experiments 接受 nameexperiment_specskip_draft(默认 false)、auto_accept_quote(默认 false)、webhook_url 五个字段(见 references/api-endpoints.md#L21-L67)。experiment_spec 内各字段在不同实验类型下的要求如下:

字段 Affinity Screening Thermostability Fluorescence Expression
experiment_type 必填 必填 必填 必填 必填
method 必填 必填
target_id 必填 必填
sequences 必填 必填 必填 必填 必填
n_replicates 建议(默认 3) 建议(默认 3) 可选 可选 可选
antigen_concentrations 可选

值得注意的默认值:antigen_concentrations 仅用于 affinity 实验,缺省为 [1000.0, 316.2, 100.0, 31.6, 0.0] nM,即约每 3.16 倍(10^0.5)递减的五浓度梯度加零浓度对照;n_replicates 为技术重复数,最小值 1。

实验生命周期:九段状态机

实验从 Draft 起步,最终到达 Done

Draft → WaitingForConfirmation → QuoteSent → WaitingForMaterials → InQueue → InProduction → DataAnalysis → InReview → Done

各状态由谁驱动、含义如何(继承自 skills/adaptyv/SKILL.md#L124-L137):

状态 行动方 说明
Draft 可编辑,无费用承诺
WaitingForConfirmation Adaptyv 审核中,报价正在生成
QuoteSent 审阅并确认报价
WaitingForMaterials Adaptyv 基因片段与靶点材料已订购
InQueue Adaptyv 材料到位,进入实验室队列
InProduction Adaptyv 检测正在运行
DataAnalysis Adaptyv 原始数据处理与 QC
InReview Adaptyv 最终校验
Done 结果可用
Canceled 任一方 实验已取消

实验中还有一个 results_status 字段跟踪数据回传进度:nonepartialall。当它进入 partial/all 时,GET /results 列表里才会出现对应的分析结果。

编辑规则与状态强相关:Draft 实验可以完整编辑(PATCH /experiments/{id});报价生成之后,只有 namedescriptionwebhook_url 仍可修改;序列也只能追加到 Draft 状态的实验,否则 POST /sequences 返回 409。

三大典型工作流

工作流 1:提交一个结合筛选(分步版)

这是技能给出的标准路径:找靶点 → 预览费用 → 创建 Draft → 提交审核 → 轮询/webhook → 取结果(完整代码见 skills/adaptyv/SKILL.md#L141-L177):

# 1. Find a target
targets = client.targets.list(search="EGFR", selfservice_only=True)
target_id = targets.items[0].id

# 2. Preview cost
estimate = client.experiments.cost_estimate({
    "experiment_spec": {
        "experiment_type": "screening",
        "method": "bli",
        "target_id": target_id,
        "sequences": {"seq1": "EVQLVESGGGLVQ...", "seq2": "MKVLVAG..."},
        "n_replicates": 3
    }
})

# 3. Create experiment (starts as Draft)
exp = client.experiments.create({
    "name": "EGFR binder screen batch 1",
    "experiment_spec": {
        "experiment_type": "screening",
        "method": "bli",
        "target_id": target_id,
        "sequences": {"seq1": "EVQLVESGGGLVQ...", "seq2": "MKVLVAG..."},
        "n_replicates": 3
    }
})

# 4. Submit for review
client.experiments.submit(exp.experiment_id)

# 5. Poll or use webhooks until Done
# 6. Retrieve results
results = client.experiments.get_results(exp.experiment_id)

工作流 2:自动化流水线(跳过 Draft + 自动接受报价)

在创建时传入 skip_draft: True 直接越过 Draft 进入 WaitingForConfirmationauto_accept_quote: True 自动接受报价并创建发票,再挂 webhook_url 接收每次状态迁移的 POST 通知:

exp = client.experiments.create({
    "name": "Auto pipeline run",
    "experiment_spec": {...},
    "skip_draft": True,
    "auto_accept_quote": True,
    "webhook_url": "https://my-server.com/webhook"
})
# Webhook fires on each status transition; poll or wait for Done

再结合 POST /experiments 的响应字段看这条链路的含义:auto_accept_quote 触发发票时会返回 stripe_hosted_invoice_urlstripe_invoice_id——也就是说该模式会真实产生 Stripe 发票。对应仓库安全报告的提示,建议只在预算与审批机制完备的自动化环境里启用这两个开关。

工作流 3:Webhook 通知

创建实验时传入 webhook_url,Adaptyv 会在每一次状态迁移时向该 URL 发 POST,载荷包含实验 ID、前一状态与新的状态。配合 GET /updates(更新流,见下文)即可实现不依赖轮询的事件驱动集成。

报价、发票与费用估算

费用相关端点是"先估价、再确认、后开票"的结构(详见 references/api-endpoints.md):

  • POST /experiments/cost-estimate:不创建实验即算价。返回 pricing_version(如 "v1_2026-01-20",说明价格按版本管理)、assay(按类型的 base + 重复数计价)、materials(结合实验的靶点材料成本)、total_cents(美元美分)。所有价格不含 VAT,税费在开票时计算;没有自助定价的靶点会返回不完整的估算。
  • GET /experiments/{id}/quote:报价元数据,含 amount_total/amount_subtotal(最小货币单位)、currency(ISO 代码,如 usd)、statusexpires_at;另有 /quote/pdf 返回 application/pdf 报价单。
  • POST /experiments/{id}/quote/confirmPOST /quotes/{quote_id}/confirm:接受报价、创建草稿发票,实验推进到 WaitingForMaterials;请求体可带 purchase_order_number;响应含 hosted_invoice_urlinvoice_id
  • POST /quotes/{quote_id}/reject:取消报价,关联实验回退到 Draft;请求体必填 reason,可附 feedback
  • GET /experiments/{id}/invoiceGET /quotes / GET /quotes/{quote_id}:发票元数据(含托管支付 URL)与组织级报价列表/明细(含 line_items 逐项价格、subtotal_centstax_centstotal_cents)。

这套设计对应生命周期表里 QuoteSent 由"你"行动的语义:报价确认是一个显式的人工决策点,除非你显式开启 auto_accept_quote

序列格式规则与批量追加

sequences 字段支持两种写法(继承自 skills/adaptyv/SKILL.md#L196-L202):

  • 简单格式:{"seq1": "EVQLVESGGGLVQPGGSLRLSCAAS"}
  • 富格式:{"seq1": {"aa_string": "EVQLVESGGGLVQ...", "control": false, "metadata": {"type": "scfv"}}}
  • 多链:用冒号分隔——"MVLS:EVQL"
  • 合法氨基酸:A, C, D, E, F, G, H, I, K, L, M, N, P, Q, R, S, T, V, W, Y(大小写不敏感,存储为大写)
  • 硬约束:序列只能追加到 Draft 状态的实验

创建后批量追加走 POST /sequencesreferences/api-endpoints.md#L327-L356):请求体为 experiment_code(人类可读实验码,如 "PROJ-001",注意这里用 code 而非 UUID)加 sequences 数组,每条含 aa_string(必填)、namecontrolmetadata;201 响应返回 added_countexperiment_idexperiment_codesequence_ids;实验不在 Draft 时返回 409。查询侧,GET /sequences 返回全实验序列(按创建倒序,列表项只含前 50 字符的 aa_previewlength),GET /sequences/{id} 才返回完整 aa_stringis_controlmetadata

靶点目录:从目录选靶到自定义靶点

GET /targets 列出可用于实验的已验证抗原,查询参数比通用分页参数多出三个领域参数(见 references/api-endpoints.md#L401-L429):

参数 类型 说明
limit int 最大条数(1–100,默认 50)
offset int 跳过条数
search string 产品名自由文本搜索
sort string 排序表达式
selfservice_only boolean 仅返回有自助定价的靶点(估价前提)
show_conjugated boolean 是否包含缀合靶点(默认仅未缀合)
detailed boolean details 块中填充富化数据(基因名、结构、序列、生物活性)

列表项关键字段:id(UUID,直接用作 experiment_spec.target_id)、namevendor_namecatalog_number(供应商目录号)、urlpricing(null 表示需要定制报价)、detailsGET /targets/{target_id} 返回单个靶点目录记录。

目录里没有想要的靶点时,走 POST /targets/request-custom 提交自定义靶点供人工审核:必填 name 与组织内唯一的 product_idsequencepdb_id 至少提供其一,可选 pdb_filemolecular_weight(kDa)、note;随后用 GET /targets/request-custom(列表,可 filter=eq(status,pending_review))和 GET /targets/request-custom/{request_id} 跟踪状态,批准后会关联出 material_id

结果回传:结果端点与字段结构

GET /results 列出已完成的分析结果(按新到旧排序),GET /experiments/{id}/results 取单个实验的结果,两者都支持 limitoffsetfiltersort(结果端点)或 search(序列端点)。结果列表项字段:

字段 类型 说明
id uuid 结果标识
title string 人类可读标题
experiment_id uuid 关联实验
result_type string "affinity""thermostability"
summary array 关键结果(按类型不同,见下)
metadata object 扩展元数据(如仪器信息)
data_package_url string/null 原始数据包下载 URL
created_at datetime 结果生成时间

summary 的类型相关结构是解读数据的关键:AffinityResultkd_meankd_stdkon_meankon_log_stdkoff_meankoff_stdreplicates 数组(每个重复带 kdkonkoffbinding_strengthkon_methodkoff_methodreplicate 索引)、sequencetarget_idThermostabilityResult 含 Tm 值与熔解曲线。GET /results/{result_id} 返回包含完整 summary 数组的详情。

过滤、排序与分页:s-expression 查询语法

所有列表端点统一支持分页(limit 1–100,默认 50;offset)、对 name 字段的自由文本 search,以及 sort 排序。过滤通过 filter 查询参数使用 s-expression 语法(完整清单继承自 skills/adaptyv/SKILL.md#L204-L221):

  • 比较:eq(field,value)neqgtgteltltecontains(field,substring)
  • 范围/集合:between(field,lo,hi)in(field,v1,v2,...)
  • 逻辑:and(expr1,expr2,...)or(...)not(expr)
  • 空值:is_null(field)is_not_null(field)
  • JSONB:at(field,key),例如 eq(at(metadata,score),42)
  • 类型转换:float()int()text()timestamp()date()

排序用 asc(field)desc(field),逗号分隔,最多 8 个键:

sort=desc(created_at),asc(name)

组合示例——筛选 2026 年以来完成且状态为 done 的实验:

filter=and(gte(created_at,2026-01-01),eq(status,done))

这套语法在 updates 流上同样有用,例如 filter=eq(type,status_change)filter=in(experiment_id,uuid1,uuid2)

更新流(Updates):轮询之外的第二通道

GET /updates 返回实验更新流(最新在前),每条含 idexperiment_idexperiment_codename(更新描述)、timestampGET /experiments/{id}/updates 返回单实验的更新(最旧在前)。更新类型有三种:status_changeprogresserror。webhook 负责实时推送,updates 流则提供可过滤、可分页的历史审计轨迹,二者是互补的关系。

错误处理与反馈回路

所有错误响应统一为两字段结构:

{
  "error": "Human-readable description",
  "request_id": "req_019462a4-b1c2-7def-8901-23456789abcd"
}

request_id 同时出现在 x-request-id 响应头中,联系支持时应附上它。这个 ID 还有第二个用途:POST /feedback/submit 端点接收 bug 报告/功能请求/一般反馈,请求体必填 request_uuid(即出问题那次的请求 UUID)与 feedback_typefeature_requestfeedbackbug_report),json_body(结构化错误细节)与 human_note(自由描述)至少提供其一,201 响应返回 referencemessage。这意味着错误上下文可以程序化地回流给供应商,而不是只停留在日志里。

令牌管理:基于 Biscuit 的密码学衰减

Foundry 的 token 采用 Biscuit 密码学衰减机制,支持为不同执行主体发放权限收窄的子 token(端点见 references/api-endpoints.md#L586-L643):

  • GET /tokens:列出调用者拥有的全部 token(root 与 attenuated),字段含 kindroot/attenuated)、expires_at(null 表示永不过期)、revoked_atparent_token_idroot_token_idattenuation_spec
  • POST /tokens/attenuate:为现有 token 创建受限版本。请求体含 token(格式为 abs0_{slug}{biscuit_base64})、attenuation(限制规格)、name,可选 attenuated_parent_token_id 支持链式衰减;限制类型覆盖组织、资源(experiments/results)、动作(read/create/update)、过期时间。201 响应返回新数据库 ID 与新的衰减 token 字符串。
  • POST /tokens/revoke:撤销调用 token 的 root 及其全部衰减后代,幂等;响应含 token_idrevoked_atchildren_revoked

对 Agent 集成的实际意义:可以按任务粒度发放"只读 + 仅 experiments 资源 + 72 小时过期"的 token,让自动化流水线持有的凭证泄露面最小化,而不是全程使用 root token。

端点总览与延伸阅读

按资源分组的 32 个端点可归纳为八族,完整请求/响应字段表见 skills/adaptyv/references/api-endpoints.md

资源族 主要端点
Experiments POST /experimentsGET /experimentsGET/PATCH /experiments/{id}POST .../submitPOST /experiments/cost-estimateGET .../quoteGET .../quote/pdfPOST .../quote/confirmGET .../invoiceGET .../resultsGET .../sequencesGET .../updates
Sequences GET /sequencesGET /sequences/{id}POST /sequences
Results GET /resultsGET /results/{id}
Targets GET /targetsGET /targets/{id}POST /targets/request-customGET /targets/request-customGET /targets/request-custom/{id}
Quotes GET /quotesGET /quotes/{id}POST /quotes/{id}/confirmPOST /quotes/{id}/reject
Tokens GET /tokensPOST /tokens/attenuatePOST /tokens/revoke
Updates GET /updates
Feedback POST /feedback/submit

技能主文档与端点参考的相对位置关系:入口是 skills/adaptyv/SKILL.md(frontmatter version: "1.2",作者 K-Dense Inc.),端点全集在 skills/adaptyv/references/api-endpoints.md,该技能在仓库技能目录中的条目见 docs/skills.md。在 Agent 侧,只需让宿主(Cursor、Claude Code、Codex 等 Agent Skills 标准宿主)按 README 的"Getting Started"安装本技能集合,当提示词涉及 Adaptyv 或代码出现 FoundryClient 时,上述认证约定、生命周期状态机与端点契约即会被自动带入上下文,直接产出可运行的集成代码。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388