This sample code-based agent is a fork of the deep research agent developed by langchain using the langgraph deepagents SDK. It has been adapted with the SAP Generative AI Hub via the SAP Cloud SDK for AI, and exposed as a FastAPI REST API service in both synchronous and asynchronous manner. Any application or agent can trigger deep research by calling the API. Especially, the asynchronous API will be helpful when the deep research agent may conduct a long-running(> 1 min) research.
The deep research agent plans and decomposes research topics from user requests, iteratively conducting multi-step research using Tavily for web search, parallel sub-agents and strategic reflection.
┌─────────────────────────────────────┐
│ API Client / Agent │
│ (any HTTP client) │
└───────────────┬─────────────────────┘
│ HTTP (REST / JSON)
▼
┌─────────────────────────────────────┐
│ FastAPI Application │ app.py
│ │
│ POST /research (sync) │
│ POST /research/jobs (async) │
│ GET /research/jobs/:id (poll) │
└───────────────┬─────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ DeepResearchAgent │ agent.py
│ create_deep_agent via deepagents SDK│
│ and SAP Cloud SDK for AI │
│ │
│ Orchestrator ──delegates─► Sub-agent│
│ (plan, synthesise, report) (search) │
└──────────────────────────────────────┘
- Client sends a research query via
POST /research(synchronous API) orPOST /research/jobs(asynchronous API). - Deep Research Agent plans the research by creating a todo list.
- Deep Research Agent delegates one or more parallel research tasks to the
research-agentsub-agent. - Sub-agent searches the web using Tavily, reflects using
think_tool, and returns structured findings with citations. - Deep Research Agent synthesises all findings, consolidates citations, and writes a comprehensive Markdown report.
- Report is returned in the API response or stored in the job store for polling.
| Variable | Required | Description |
|---|---|---|
AICORE_AUTH_URL |
✅ | SAP AI Core OAuth token endpoint |
AICORE_CLIENT_ID |
✅ | SAP AI Core client ID |
AICORE_CLIENT_SECRET |
✅ | SAP AI Core client secret |
AICORE_RESOURCE_GROUP |
✅ | Resource group (default: default) |
AICORE_BASE_URL |
✅ | SAP AI Core API base URL |
TAVILY_API_KEY |
✅ | Tavily search API key |
MODEL_NAME |
✅ | The target LLM in SAP Generative AI Hub (default: gpt-4o-mini) |
MAX_RESEARCHER_ITERATIONS |
❌ | Max round of research (default: 2) |
MAX_CONCURRENT_RESEARCH_UNITS |
❌ | Max researches in parallel (default: 3) |
SUPPLIER_API_URL |
❌ | Ariba OData supplier search endpoint (default: https://xyz.hana.ondemand.com/Ariba_SearchSupplier/Suppliers) |
SUPPLIER_AUTH_URL |
❌ | OAuth 2.0 token endpoint for the supplier API (default: https://xyz.authentication.eu10.hana.ondemand.com) |
SUPPLIER_CLIENT_ID |
❌ | Client ID for supplier API authentication |
SUPPLIER_CLIENT_SECRET |
❌ | Client secret for supplier API authentication |
HOST |
❌ | Server bind host (default: 0.0.0.0) |
PORT |
❌ | Server bind port (default: 10000) |
| Method | Path | Description |
|---|---|---|
POST |
/research |
Synchronous — runs research and returns the completed report. Blocks until done (typically several minutes). |
POST |
/research/jobs |
Asynchronous — submits a research job, returns a job_id immediately (HTTP 202). |
GET |
/research/jobs/{job_id} |
Poll job status (running / completed / failed) and retrieve the result. |
{ "query": "Research the latest advances in AI agent frameworks" }{
"query": "Research the latest advances in AI agent frameworks",
"result": "# Research Report\n...",
"status": "completed"
}{
"job_id": "3f4a1b2c-...",
"query": "Research the latest advances in AI agent frameworks",
"status": "running"
}{
"job_id": "3f4a1b2c-...",
"query": "Research the latest advances in AI agent frameworks",
"status": "completed",
"result": "# Research Report\n...",
"error": null
}| File | Purpose |
|---|---|
app/agent.py |
DeepResearchAgent — builds the LangGraph multi-agent pipeline and exposes stream() and run() methods |
app/app.py |
FastAPI application with sync and async research endpoints |
app/manifest.yaml |
Cloud Foundry deployment manifest |
app/research_agent/ |
Prompt templates and Tavily search tools |
- Python 3.11+
- Install uv package manager
- An SAP AI Core instance with Generative AI Hub. by default,
gpt-4o-minimodel is used. - Tavily API key (free tier available)
cd 20-joule-a2a-code-based-agent/deep_research_api
# create a virtual env for 20-joule-a2a-code-based-agent
uv venv
# activate the virtual env
source .venv/bin/activate
# install the dependencies
cd app
uv pip install -r requirements.txtcp .env.example .envEdit .env and fill in your SAP AI Core and Tavily credentials
python app.pyThe server starts at http://localhost:10000. Interactive API docs are available at
http://localhost:10000/docs.
curl -X POST http://localhost:10000/research \
-H "Content-Type: application/json" \
-d '{"query": "Research the latest advances in AI agent frameworks"}'# Submit job
curl -X POST http://localhost:10000/research/jobs \
-H "Content-Type: application/json" \
-d '{"query": "Research the latest advances in AI agent frameworks"}'
# Periodically poll result (replace <job_id> with the returned job_id).
# e.g. repeat every 10 second until the job status become completed
curl http://localhost:10000/research/jobs/<job_id>python test_client.pycd 20-joule-a2a-code-based-agent/deep_research_api/app
cp manifest.template.yaml manifest.yamlFill in all <placeholder> values with your actual SAP AI Core credentials, tavily-key etc.
cf login
cf pushObtain the deployment URL, then you can use it in any http client.
As highlighted in the official help centre of Joule Studio here, With synchronous communication, Joule expects the response from agent server in < 60 seconds..
According the official quota of Action tasks, a synchronous API call to BYOA through Action project may hit connection timeout(1 minutes), socket timeout(gateway timeout for 3 minutes) etc.

In conclusion, the viable approaches of integrating a long-running agent with SAP Joule must be through such asynchronous communication. However, it is important to note that the following solutions are only applicable to those long-running within a 5 minutes timeframe.
Please refer to help document about Asynchronous API Request.
DO READ its Platform requirement and Technical Prerequisites carefully.
- Bi-directional communication (callback support) is currently only supported for IAS-based integrations.
- Non-IAS-based integrations are not yet compatible with this asynchronous callback model.
The following steps is ought to be performed in SAP BTP Sub Account where SAP Build Process Automation resides.
| Properties | Values |
|---|---|
| Name | deep-research-api |
| Type | http |
| Description | deep-research-agent for Joule integration with REST API |
| URL | the deployment URL of deep-research-api application on Cloud Foundry |
| sap.applicationdevelopment.actions.enabled | true |
| sap.processautomation.enable | true |
As the APIs are REST format, therefore you will need to create the action from scratch.
| Properties | Values |
|---|---|
| Name | Submit Research Job |
| Http Method | POST |
| Endpoint | /research/jobs |
| Description | Submit a Research Job, and return its job_id |
| Input Body | sample json { "query": "Research the latest advances in AI agent frameworks" } |
| Output Body | sample json { "job_id": "3f4a1b2c-...", "query": "Research the latest advances in AI agent frameworks", "status": "running"} |
| Properties | Values |
|---|---|
| Name | Poll Research Job Result |
| Http Method | GET |
| Endpoint | /research/jobs/{job_id} |
| Description | Poll job status (running / completed / failed) and retrieve the result. |
| Input Parameter | Key: job_id, Parameter: path, Type: string |
| Output Body | sample json { "job_id": "3f4a1b2c-...", "query": "Research the latest advances in AI agent frameworks","status": "completed", "result": "# Research Report\n...","error": null} |
| Properties | Values |
|---|---|
| Name | Synchronous Research |
| Http Method | POST |
| Endpoint | /research |
| Description | Synchronous runs research and returns the completed report. Blocks until done (typically several minutes) |
| Input Parameter | Key: job_id, Parameter: path, Type: string |
| Output Body | sample json { "job_id": "3f4a1b2c-...", "query": "Research the latest advances in AI agent frameworks","status": "completed", "result": "# Research Report\n...","error": null} |
Make sure you have tested the actions with the destination deep-research-api created in step 1. Once it all works as required, then release and publish the Action project
| Properties | Values |
|---|---|
| Name | Deep Research Process |
| Description | A process to invoke remote Deep Research Agent through async REST api |
| Process Input | Name: User Input, Type: string |
| Process Output | Name: Research Report, Type: string |
| The condition of looping | job.result.status == 'running' |
You can import the Research Process artifact through SAP Build Process Automation Lobby
You can import the Research Skill artifact through SAP Build Process Automation Lobby
The skill must be deployed to the same environment as the Deep Research Process in step 3.
Once the joule client is launched, you can enter a research task like
Research different approaches to custom AI Agent development with Joule Studio Agent Builder, Joule Studio Code Editor and SAP Cloud SDK for AI

It will trigger the process, which can be monitored through Control Tower > Monitoring > Proeess and Workflow Instances


