Generates and deploys pro-code AI agents using LangGraph and SAP GenAI Hub to SAP BTP Cloud Foundry as REST APIs, creates Joule capabilities with A2A actions. Supports TypeScript (Express/CAP) and Python.
npx claudepluginhub sap-samples/joule-a2a-agent-toolkitThis skill uses the workspace's default tool permissions.
This skill generates a complete pro-code AI agent project that:
evals/evals.jsonreferences/cf-deployment-cap-typescript.mdreferences/cf-deployment-typescript.mdreferences/cf-deployment.mdreferences/joule-capability.mdreferences/langgraph-a2a-agent-cap-typescript.mdreferences/langgraph-a2a-agent-typescript.mdreferences/langgraph-a2a-agent.mdscripts/create-destination.shscripts/scaffold-ts.shscripts/scaffold.pyProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
Analyzes competition with Porter's Five Forces, Blue Ocean Strategy, and positioning maps to identify differentiation opportunities and market positioning for startups and pitches.
Share bugs, ideas, or general feedback.
This skill generates a complete pro-code AI agent project that:
cf push or MTA)SAP Joule can orchestrate external agents using the A2A (Agent-to-Agent) protocol. The flow is:
/.well-known/agent.jsonThe connection between Joule and your agent uses a BTP Destination + a Joule capability YAML that defines an agent-request action type.
Joule DTA Schema Version 3.28.0+ Required: Code-based agents (BYOA) using the agent-request action type are supported as of DTA schema version 3.28.0. The capability.sapdas.yaml must specify schema_version: "3.28.0".
If your Joule tenant runs an older schema version, the compile will succeed but deploy will fail with: "Schema version defined in config file is greater than the current schema version of Joule".
How to check your tenant's version:
joule login --use-env (or joule login )joule statusOther prerequisites:
npm install -g @sap/joule-studio-clicf login or cf login )joule login or joule login --use-env)extensibility_developer + capabilityadmin for Joule deploymentsmbt (MTA Build Tool): npm install -g mbtcf install-plugin multiapps (required for cf deploy with .mtar files)Before you start, make sure Claude Code is started with the toolkit plugin and you are logged in to both CLIs:
# 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
When the user asks to create/modify a Joule A2A agent, follow these steps:
Ask the user:
gpt-4.1)If the user is unsure about BTP details, generate the project anyway with placeholder values.
The project can be generated in three configurations:
Run the scaffold script:
bash <skill-path>/scripts/scaffold-ts.sh \
--name <agent-name> \
--framework express \
--namespace <company-namespace> \
--output <output-dir> \
--description "<agent description>" \
--landscape <cf-landscape>
Or manually using 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
Run the scaffold script:
bash <skill-path>/scripts/scaffold-ts.sh \
--name <agent-name> \
--framework cap \
--namespace <company-namespace> \
--output <output-dir> \
--description "<agent description>" \
--landscape <cf-landscape>
Or manually using 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
Run the scaffold script:
python <skill-path>/scripts/scaffold.py \
--name <agent-name> \
--namespace <company-namespace> \
--output <output-dir> \
--description "<agent description>" \
--landscape <cf-landscape>
Or manually using references/langgraph-a2a-agent.md + references/cf-deployment.md.
| Aspect | TS Express | TS CAP | Python |
|---|---|---|---|
| Server | 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 |
| LLM | OrchestrationClient | OrchestrationClient | langchain-openai ChatOpenAI (direct AI Core endpoint) |
| Deploy | cf push (manifest.yml) | mbt build && cf deploy (mta.yaml) | cf push (manifest.yml) |
| Auth | Manual | Built-in CAP auth | Manual |
| Agent pattern | createReactAgent | StateGraph (manual) | create_react_agent |
| Interrupt support | Basic (question heuristic) | Full (LangGraph interrupt()) | Structured response format |
| Buildpack | nodejs_buildpack | nodejs_buildpack (via MTA) | python_buildpack |
| Reference | langgraph-a2a-agent-typescript.md | langgraph-a2a-agent-cap-typescript.md | langgraph-a2a-agent.md |
The Joule capability YAML files are identical regardless of language/framework.
Based on the user's requirements:
Define tools — In TypeScript: functions created with tool() and Zod schemas. In Python: functions decorated with @tool. Map each user requirement to a tool function.
src/tools.tssrv/tools/tools.tsapp/tools.pyConfigure the agent — Set the system instruction to match the agent's purpose.
SYSTEM_PROMPT in src/agent.tssrv/utils/prompts.tsSYSTEM_INSTRUCTION in app/agent.pySet up the Agent Card — Name, skills, and supported modes.
src/agentCard.tsagentCard in srv/server.tsapp/agent_card.pyConfigure capability.sapdas.yaml — The scenario description in scenarios/invoke_agent.yaml must clearly describe when Joule should invoke this agent.
Read references/cf-deployment-typescript.md or 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
Read 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
After deployment, create a BTP Destination pointing to the agent's URL:
bash <skill-path>/scripts/create-destination.sh \
--agent-name <agent-name> \
--destination-name <DESTINATION_NAME> \
--landscape <cf-landscape>
The destination name must match system_aliases.<AliasName>.destination in capability.sapdas.yaml.
Read references/joule-capability.md for the complete reference.
# 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>"
If it doesn't work, check: destination configuration, agent card accessibility, capability scenario description matching, and CF app logs (cf logs <app-name> --recent).
When the user wants to change an existing agent:
Adding a new tool: Add the tool function, register it in the agent, add a skill to the agent card. Redeploy to CF.
Changing the model: Update MODEL_NAME env var. The model must be deployed on your AI Core instance.
Updating the Joule capability: Edit capability.sapdas.yaml and scenario files, recompile and redeploy with joule deploy ./da.sapdas.yaml --compile.
Scaling: Adjust instances and memory in manifest.yml (Express) or mta.yaml (CAP).
Read these before generating code:
references/langgraph-a2a-agent-typescript.md — TypeScript Express templates (jsonRpcHandler, agentCardHandler, createReactAgent, OrchestrationClient)references/langgraph-a2a-agent-cap-typescript.md — TypeScript CAP templates (cds.on bootstrap, StateGraph, interrupt support)references/langgraph-a2a-agent.md — Python templates (A2AStarletteApplication, create_react_agent, langchain-openai with direct AI Core credentials)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, Procfilereferences/joule-capability.md — Multi-file DTA format: capability.sapdas.yaml (schema 3.28.0), da.sapdas.yaml (schema 1.4.0), functions/, scenarios/, multi-turn contextId/taskId patternmessage/send and optionally message/stream methods./.well-known/agent.json for Joule's discovery.OrchestrationClient from @sap-ai-sdk/langchain (auto-reads VCAP_SERVICES).langchain-openai ChatOpenAI pointed at AI Core's OpenAI-compatible endpoint (do NOT use generative-ai-hub-sdk — pydantic version conflict with a2a-sdk).@sap/joule-cli) requires the capabilityadmin and extensibility_developer roles.da.sapdas.yaml uses schema version 1.4.0. The capability.sapdas.yaml uses 3.28.0.joule.ext — the metadata.namespace in capability.sapdas.yaml must be set to joule.ext. Using any other namespace (e.g. mycompany) will cause joule deploy to fail with a namespace validation error. The scaffold scripts default to joule.ext.mbt (npm install -g mbt) for building and the MTA CF CLI plugin (cf install-plugin multiapps) for cf deploy to work with .mtar files. See CAP deploy to CF guide.