关于 joule-a2a-agent
joule-a2a-agent 是用于生成 SAP Joule A2A Agent 项目的技能,面向在 SAP BTP Cloud Foundry 上构建并部署服务的开发者。它提供 TypeScript 或 Python 项目脚手架,并涵盖 Joule capability 的创建和部署流程。
主要功能
- 01生成 TypeScript 或 Python Agent 项目
- 02提供 Express 或 CAP 配置
- 03集成 LangGraph 与 SAP GenAI Hub
- 04部署至 SAP BTP Cloud Foundry
- 05创建并部署 Joule capability
适用场景
- 01创建可供 Joule 调用的 A2A Agent
- 02在 Cloud Foundry 部署 Agent REST API
- 03为现有 Agent 添加工具或更改模型
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sap-samples/ joule-a2a-agent-toolkit --skill joule-a2a-agent安装后在 Claude Code 中输入/joule-a2a-agent确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/cf-deployment-cap-typescript.mdcf-deployment-typescript.mdcf-deployment.mdjoule-capability.mdlanggraph-a2a-agent-cap-typescript.mdlanggraph-a2a-agent-typescript.mdlanggraph-a2a-agent.mdscripts/create-destination.shscaffold-ts.shscaffold.py详细介绍
SAP BTP Cloud Foundry 上的 Joule A2A Agent
此技能可生成一个完整的专业代码 AI Agent 项目,该项目:
- 使用 LangGraph + @a2a-js/sdk 0.3.10 和 SAP GenAI Hub(OrchestrationClient)作为 LLM 提供方,实现支持 A2A 协议 v0.3.0 的 Agent
- 将其部署到 SAP BTP Cloud Foundry,作为 REST API(通过
cf push或 MTA) - 使用多文件 DTA 格式创建包含 A2A 操作的 Joule capability
- 提供用于编译和部署 capability 到 Joule 的 CLI 命令
工作原理 — 概览
SAP Joule 可使用 A2A(Agent-to-Agent)协议编排外部 Agent。流程如下:
- 你的 Agent 作为 TypeScript 或 Python Web 服务运行在 Cloud Foundry 上,并公开兼容 A2A 的端点
- Joule 通过读取 Agent Card 发现你的 Agent,其路径为
/.well-known/agent.json - 当用户的提示词与 Agent 的能力匹配时,Joule 会向你的 Agent 发送 A2A 任务
- 你的 Agent 使用 LangGraph 处理请求(包括工具、通过 SAP GenAI Hub 进行 LLM 推理等),并返回结果
- Joule 会在聊天中向用户展示结果
Joule 与你的 Agent 之间通过 BTP Destination 和 Joule capability YAML 建立连接,该 YAML 定义了 agent-request 操作类型。
前提条件
需要 Joule DTA Schema Version 3.28.0+: 从 DTA schema 版本 3.28.0 开始,支持使用 agent-request 操作类型的基于代码的 Agent(BYOA)。capability.sapdas.yaml 必须指定 schema_version: "3.28.0"。
如果你的 Joule 租户使用较旧的 schema 版本,编译会成功,但部署会失败,并显示:“配置文件中定义的 Schema 版本高于 Joule 当前的 Schema 版本”。
如何检查租户的版本:
- 登录:
joule login --use-env(或joule login) - 检查状态:
joule status - 尝试部署 — 如果出现 schema 错误,则需要更新租户
- 联系你的 BTP 管理员,请求更新 Joule 服务
其他前提条件:
- 已启用 Cloud Foundry 的 SAP BTP 子账户
- 已部署 GenAI Hub 模型的 AI Core 服务实例
- 已安装 Joule CLI:
npm install -g @sap/joule-studio-cli - 已安装并登录 CF CLI(
cf login或cf login) - 已登录 Joule CLI(
joule login或joule login --use-env) - 已为 Joule Studio CLI 配置 Joule App2App IAS 流程(分配所需角色)
- BTP 角色:用于 Joule 部署的
extensibility_developer+capabilityadmin - 对于 CAP Agent:
mbt(MTA Build Tool):npm install -g mbt - 对于 CAP Agent:MTA CF CLI 插件:
cf install-plugin multiapps(通过.mtar文件运行cf deploy时需要)
开始之前,请确保 Claude Code 已通过工具包插件启动,并且你已登录这两个 CLI:
# Start Claude Code with the SAP A2A Agent Toolkit plugin
claude --plugin-dir <path-to-sap-a2a-agent-toolkit>
# Log in to Cloud Foundry
cf login -a https://api.cf.<landscape>.hana.ondemand.com
# Log in to Joule
joule login
工作流
当用户要求创建或修改 Joule A2A Agent 时,请执行以下步骤:
步骤 1:收集需求
询问用户:
- 语言 — TypeScript(默认)还是 Python?
- 框架 — Express(默认,轻量)还是 CAP(企业级,通过 MTA 部署)?注意:CAP 仅支持 TypeScript。
- Agent 名称和用途 — 这个 Agent 应该做什么?
- 工具/API — Agent 应调用哪些外部服务或 API?
- SAP GenAI Hub 模型 — AI Core 上部署了哪个模型?(默认:
gpt-4.1) - BTP 环境详情 — CF API 端点、组织、空间(如果用户知道)
如果用户不确定 BTP 详情,仍需生成项目,并使用占位值。
步骤 2:生成 Agent 项目
项目可通过以下三种配置生成:
a) TypeScript + Express(默认)
运行脚手架脚本:
bash <skill-path>/scripts/scaffold-ts.sh \
--name <agent-name> \
--framework express \
--namespace <company-namespace> \
--output <output-dir> \
--description "<agent description>" \
--landscape <cf-landscape>
也可以使用 references/langgraph-a2a-agent-typescript.md + references/cf-deployment-typescript.md 手动生成。
<agent-name>/
├── src/
│ ├── index.ts # Express + A2A server entry point
│ ├── agent.ts # LangGraph.js ReAct agent
│ ├── executor.ts # A2A protocol bridge
│ ├── agentCard.ts # Agent Card definition
│ ├── tools.ts # Agent's tools (Zod schemas)
│ └── llm.ts # SAP GenAI Hub configuration
├── joule-capability/
│ ├── capability.sapdas.yaml
│ ├── capability_context.yaml
│ ├── da.sapdas.yaml
│ ├── functions/call_agent.yaml
│ └── scenarios/invoke_agent.yaml
├── package.json
├── tsconfig.json
├── manifest.yml
├── Procfile
├── .env.example
└── README.md
b) TypeScript + CAP
运行脚手架脚本:
bash <skill-path>/scripts/scaffold-ts.sh \
--name <agent-name> \
--framework cap \
--namespace <company-namespace> \
--output <output-dir> \
--description "<agent description>" \
--landscape <cf-landscape>
也可以使用 references/langgraph-a2a-agent-cap-typescript.md + references/cf-deployment-cap-typescript.md 手动生成。
<agent-name>/
├── srv/
│ ├── server.ts # CAP bootstrap + A2A Express endpoints
│ ├── agent-executor.ts # LangGraph StateGraph agent orchestrator
│ ├── service.cds # CDS service definition
│ ├── tools/
│ │ └── tools.ts # Agent tools (Zod schemas)
│ └── utils/
│ ├── prompts.ts # System prompt
│ ├── a2aToLangchain.ts # A2A → LangChain converter
│ ├── a2a-operations.ts # A2A event helpers
│ └── helpers.ts # URL helpers
├── joule-capability/
│ ├── capability.sapdas.yaml
│ ├── capability_context.yaml
│ ├── da.sapdas.yaml
│ ├── functions/call_agent.yaml
│ └── scenarios/invoke_agent.yaml
├── package.json
├── tsconfig.json
├── mta.yaml
├── .cdsrc.sample.json
├── .env.example
└── README.md
c) Python + Express
运行脚手架脚本:
python <skill-path>/scripts/scaffold.py \
--name <agent-name> \
--namespace <company-namespace> \
--output <output-dir> \
--description "<agent description>" \
--landscape <cf-landscape>
或者,手动参考 references/langgraph-a2a-agent.md + references/cf-deployment.md。
主要差异
| 方面 | TS Express | TS CAP | Python |
|---|---|---|---|
| 服务端 | Express + jsonRpcHandler/agentCardHandler | CAP + cds.on("bootstrap") | Starlette + A2AStarletteApplication |
| A2A SDK | @a2a-js/sdk 0.3.10 | @a2a-js/sdk 0.3.10 | a2a-sdk >=0.2.7 |
| 大模型 | OrchestrationClient | OrchestrationClient | langchain-openai ChatOpenAI(直接连接 AI Core 端点) |
| 部署 | cf push(manifest.yml) | mbt build && cf deploy(mta.yaml) | cf push(manifest.yml) |
| 身份验证 | 手动 | 内置 CAP 身份验证 | 手动 |
| Agent 模式 | createReactAgent | StateGraph(手动) | create_react_agent |
| 中断支持 | 基础(问题启发式) | 完整(LangGraph interrupt()) | 结构化响应格式 |
| 构建包 | nodejs_buildpack | nodejs_buildpack(通过 MTA) | python_buildpack |
| 参考 | langgraph-a2a-agent-typescript.md | langgraph-a2a-agent-cap-typescript.md | langgraph-a2a-agent.md |
无论使用哪种语言或框架,Joule capability YAML 文件都完全相同。
步骤 3:自定义 Agent
根据用户的需求:
-
定义工具 — 在 TypeScript 中,使用
tool()和 Zod 架构创建函数;在 Python 中,使用@tool装饰函数。将每项用户需求映射到一个工具函数。- Express TS:
src/tools.ts - CAP TS:
srv/tools/tools.ts - Python:
app/tools.py
- Express TS:
-
配置 Agent — 设置与 Agent 用途相符的系统指令。
- Express TS:
src/agent.ts中的SYSTEM_PROMPT - CAP TS:
srv/utils/prompts.ts - Python:
app/agent.py中的SYSTEM_INSTRUCTION
- Express TS:
-
设置 Agent Card — 名称、技能和支持的模式。
- Express TS:
src/agentCard.ts - CAP TS:
srv/server.ts中的agentCard - Python:
app/agent_card.py
- Express TS:
-
配置
capability.sapdas.yaml—scenarios/invoke_agent.yaml中的场景描述必须清楚说明 Joule 应在何时调用此 Agent。
步骤 4:部署到 Cloud Foundry
Express(TypeScript 或 Python)
阅读 references/cf-deployment-typescript.md 或 references/cf-deployment.md。
cd <agent-name>
npm install
npm run build # TypeScript only — must compile before push
cf push
curl https://<app-url>/.well-known/agent.json
CAP(TypeScript)
阅读 references/cf-deployment-cap-typescript.md。
cd <agent-name>
npm install
mbt build
cf deploy mta_archives/<agent-name>_1.0.0.mtar
curl https://<agent-name>-srv.cfapps.<landscape>.hana.ondemand.com/.well-known/agent.json
步骤 5:创建 BTP Destination
部署后,创建一个指向 Agent URL 的 BTP Destination:
bash <skill-path>/scripts/create-destination.sh \
--agent-name <agent-name> \
--destination-name <DESTINATION_NAME> \
--landscape <cf-landscape>
Destination 名称必须与 capability.sapdas.yaml 中的 system_aliases.<AliasName>.destination 相匹配。
步骤 6:部署 Joule Capability
阅读 references/joule-capability.md,了解完整参考信息。
# Install Joule CLI (if not installed)
npm install -g @sap/joule-cli
# Authenticate
joule login # or joule login --use-env
# Navigate to the joule-capability directory
cd joule-capability
# Compile + deploy
joule deploy ./da.sapdas.yaml --compile -n "<assistant_name>"
步骤 7:测试集成
- 在 SAP 系统中打开 Joule
- 输入与 capability 场景描述相符的提示词
- Joule 应通过 A2A 将请求路由到你的 Agent
- 确认响应正确返回
如果无法正常工作,请检查:Destination 配置、Agent Card 的可访问性、capability 场景描述是否匹配,以及 CF 应用日志(cf logs <app-name> --recent)。
修改现有 Agent
用户希望修改现有 Agent 时:
-
添加新工具:添加工具函数,在 Agent 中注册该工具,并向 Agent Card 添加一项技能。然后重新部署到 CF。
-
更改模型:更新
MODEL_NAME环境变量。该模型必须已部署在你的 AI Core 实例上。 -
更新 Joule capability:编辑
capability.sapdas.yaml和场景文件,重新编译并使用joule deploy ./da.sapdas.yaml --compile重新部署。 -
扩缩容:调整
manifest.yml(Express)或mta.yaml(CAP)中的instances和memory。
参考文件
生成代码前请阅读以下文件:
LangGraph + A2A SDK
references/langgraph-a2a-agent-typescript.md— TypeScript Express 模板(jsonRpcHandler、agentCardHandler、createReactAgent、OrchestrationClient)references/langgraph-a2a-agent-cap-typescript.md— TypeScript CAP 模板(cds.on 启动、StateGraph、中断支持)references/langgraph-a2a-agent.md— Python 模板(A2AStarletteApplication、create_react_agent、使用直接 AI Core 凭据的 langchain-openai)
Cloud Foundry 部署
references/cf-deployment-typescript.md— TypeScript Express:manifest.yml、package.json、cf pushreferences/cf-deployment-cap-typescript.md— TypeScript CAP:mta.yaml、mbt build、cf deployreferences/cf-deployment.md— Python:manifest.yml、requirements.txt、Procfile
Joule 集成
references/joule-capability.md— 多文件 DTA 格式:capability.sapdas.yaml(schema 3.28.0)、da.sapdas.yaml(schema 1.4.0)、functions/、scenarios/、多轮对话的 contextId/taskId 模式
重要说明
- A2A protocol v0.3.0 使用基于 HTTP(S) 的 JSON-RPC 2.0。你的 Agent 必须处理
message/send,并可选地处理message/stream方法。 - Agent Card 必须托管在
/.well-known/agent.json,以供 Joule 发现。 - SAP GenAI Hub 需要 AI Core 服务实例,以及所需模型的部署。
- TypeScript Agent 使用来自
@sap-ai-sdk/langchain的OrchestrationClient(自动读取 VCAP_SERVICES)。 - Python Agent 使用指向 AI Core OpenAI 兼容端点的
langchain-openaiChatOpenAI(不要使用generative-ai-hub-sdk— 它与a2a-sdk存在 pydantic 版本冲突)。 - Joule CLI(
@sap/joule-cli)需要capabilityadmin和extensibility_developer角色。 - BTP 中的 Destination 必须使用 NoAuthentication 或 OAuth2ClientCredentials。
- CAP 仅适用于 TypeScript。Python 仅使用 Express(Starlette)。
da.sapdas.yaml使用 schema 版本1.4.0。capability.sapdas.yaml使用3.28.0。- 命名空间必须为
joule.ext—capability.sapdas.yaml中的metadata.namespace必须设置为joule.ext。使用任何其他命名空间(例如mycompany)都会导致joule deploy因命名空间验证错误而失败。脚手架脚本默认使用joule.ext。 - CAP Agent 需要另外两个工具:用于构建的
mbt(npm install -g mbt),以及用于让cf deploy能处理.mtar文件的 MTA CF CLI 插件(cf install-plugin multiapps)。请参阅 CAP 部署到 CF 指南。