Skip to content

Commit 24a5f2e

Browse files
Merge branch 'main' into main
2 parents c9a5c89 + dd1a153 commit 24a5f2e

89 files changed

Lines changed: 20849 additions & 27 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env_integration_tests.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,8 @@ CLOUD_SDK_CFG_DATA_ANONYMIZATION_DEFAULT_KEY=your-base64-encoded-client-private-
2222

2323
CLOUD_SDK_CFG_SDM_DEFAULT_URI=https://your-sdm-api-uri-here
2424
CLOUD_SDK_CFG_SDM_DEFAULT_UAA='{"url":"https://your-auth-url","clientid":"your-client-id","clientsecret":"your-client-secret","identityzone":"your-identity-zone"}'
25+
26+
CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_APPLICATION_URL=https://your-agent-memory-api-url-here
27+
CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_UAA_URL=https://your-auth-url-here
28+
CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_UAA_CLIENTID=your-client-id-here
29+
CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_UAA_CLIENTSECRET=your-client-secret-here

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The Python SDK offers a clean, type-safe API following Python best practices whi
1010

1111
### Key Features
1212

13+
- **Agent Decorators**
1314
- **AI Core Integration**
1415
- **Audit Log Service**
1516
- **Destination Service**
@@ -59,6 +60,7 @@ The SDK automatically resolves configuration from multiple sources with the foll
5960

6061
Each module has comprehensive usage guides:
6162

63+
- [Agent Decorators](src/sap_cloud_sdk/agent_decorators/user-guide.md)
6264
- [AuditLog](src/sap_cloud_sdk/core/auditlog/user-guide.md)
6365
- [Destination](src/sap_cloud_sdk/destination/user-guide.md)
6466
- [DMS](src/sap_cloud_sdk/dms/user-guide.md)

docs/INTEGRATION_TESTS.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ Integration tests verify that the SDK modules work correctly with real external
99
## Prerequisites
1010

1111
### Required Tools
12+
1213
- **Python 3.11+**: Required for running the tests
1314
- **uv**: Package manager for dependency management
1415

1516
### Install Dependencies
17+
1618
```bash
1719
# Install all dependencies including test dependencies
1820
uv sync --all-extras
@@ -62,6 +64,18 @@ CLOUD_SDK_CFG_DESTINATION_DEFAULT_URI=https://your-destination-configuration-uri
6264
CLOUD_SDK_CFG_DESTINATION_DEFAULT_IDENTITYZONE=your-identity-zone-here
6365
```
6466

67+
### Agent Memory Integration Tests
68+
69+
For Agent Memory integration tests, configure the following variables in `.env_integration_tests`:
70+
71+
```bash
72+
# Agent Memory Configuration
73+
CLOUD_SDK_CFG_AGENT_MEMORY_DEFAULT_URL=https://your-agent-memory-api-url
74+
CLOUD_SDK_CFG_AGENT_MEMORY_DEFAULT_AUTH_URL=https://your-auth-url
75+
CLOUD_SDK_CFG_AGENT_MEMORY_DEFAULT_CLIENTID=your-client-id
76+
CLOUD_SDK_CFG_AGENT_MEMORY_DEFAULT_CLIENTSECRET=your-client-secret
77+
```
78+
6579
### Data Anonymization Integration Tests
6680

6781
For Data Anonymization integration tests, configure the following variables in `.env_integration_tests`:
@@ -95,6 +109,7 @@ uv run pytest tests/core/integration/auditlog -v
95109
uv run pytest tests/core/integration/data_anonymization -v
96110
uv run pytest tests/objectstore/integration/ -v
97111
uv run pytest tests/destination/integration/ -v
112+
uv run pytest tests/agent_memory/integration/ -v
98113
```
99114

100115
### BDD Scenarios

pyproject.toml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "sap-cloud-sdk"
3-
version = "0.15.0"
3+
version = "0.19.0"
44
description = "SAP Cloud SDK for Python"
55
readme = "README.md"
66
license = "Apache-2.0"
@@ -20,7 +20,7 @@ dependencies = [
2020
"opentelemetry-processor-baggage~=0.61b0",
2121
"traceloop-sdk~=0.54.0",
2222
"httpx>=0.27.0",
23-
"PyJWT~=2.10.1",
23+
"PyJWT~=2.12.1",
2424
"protobuf>=4.25.0",
2525
"protovalidate>=0.13.0",
2626
"grpcio>=1.60.0",
@@ -31,10 +31,13 @@ dependencies = [
3131
# wrapt 2.x removed the `module` keyword, causing the LangChain instrumentor
3232
# initialization to fail at import time, which silently disables LangChain
3333
"wrapt<2",
34+
"mcp>=1.1.0",
3435
]
3536

3637
[project.optional-dependencies]
38+
extensibility = ["a2a-sdk>=0.2.0"]
3739
starlette = ["starlette>=0.40.0"]
40+
langchain = ["langchain-core>=1.2.7"]
3841

3942
[build-system]
4043
requires = ["hatchling"]
@@ -47,6 +50,7 @@ packages = ["src/sap_cloud_sdk", "src/buf"]
4750
dev = [
4851
"pytest>=8.4.2",
4952
"pytest-cov>=7.0.0",
53+
"pytest-asyncio>=1.0.0",
5054
"pytest-bdd>=7.2.0",
5155
"python-dotenv>=1.0.0",
5256
"ty>=0.0.21",
@@ -55,6 +59,8 @@ dev = [
5559
"starlette>=0.40.0",
5660
"anyio>=3.6.2",
5761
"httpx>=0.27.0",
62+
"a2a-sdk>=0.2.0",
63+
"langchain-core>=1.2.7",
5864
]
5965

6066
[tool.pytest.ini_options]
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""SAP Cloud SDK for Python - Agent Decorators module.
2+
3+
Decorator-based configuration-as-code for SAP AI agents. Developers
4+
annotate functions with decorators to expose configuration fields
5+
(prompts, models, settings) to a low-code UI.
6+
7+
Usage:
8+
from sap_cloud_sdk.agent_decorators import (
9+
prompt_section,
10+
agent_config,
11+
agent_model,
12+
)
13+
14+
@prompt_section(
15+
key="prompts.system",
16+
label="System Prompt",
17+
description="Main system prompt for the agent",
18+
)
19+
def system_prompt() -> str:
20+
return "You are a helpful assistant."
21+
"""
22+
23+
from sap_cloud_sdk.agent_decorators.decorators import (
24+
agent_config,
25+
agent_model,
26+
prompt_section,
27+
)
28+
from sap_cloud_sdk.agent_decorators.exceptions import (
29+
AgentDecoratorError,
30+
)
31+
32+
__all__ = [
33+
# Decorators
34+
"prompt_section",
35+
"agent_config",
36+
"agent_model",
37+
# Exceptions
38+
"AgentDecoratorError",
39+
]
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
"""Decorator functions for exposing agent configuration fields.
2+
3+
Each decorator is a marker — it annotates a zero-argument function
4+
whose return value is the coded default for a configuration field.
5+
External tooling discovers these markers in source text and extracts
6+
their arguments and return values.
7+
8+
At decoration time only the *key* is validated; the function is
9+
returned unchanged.
10+
"""
11+
12+
from typing import Any, Callable, Optional
13+
14+
from .exceptions import AgentDecoratorError
15+
16+
17+
def _validate_key(key: str) -> None:
18+
"""Validate a decorator key.
19+
20+
Raises:
21+
AgentDecoratorError: If the key is empty or whitespace-only.
22+
"""
23+
if not key or not key.strip():
24+
raise AgentDecoratorError(
25+
f"Decorator key must be a non-empty string, got {key!r}"
26+
)
27+
28+
29+
def prompt_section(
30+
key: str,
31+
label: str,
32+
description: str,
33+
validation: Optional[dict[str, Any]] = None,
34+
) -> Callable:
35+
"""Expose a prompt section for editing.
36+
37+
Args:
38+
key: Unique identifier for this prompt (e.g. ``"prompts.system"``).
39+
label: Human-readable label shown in the UI.
40+
description: Help text explaining what this prompt does.
41+
validation: Optional validation rules as a dict
42+
(e.g. ``{"format": "text", "max_length": 500}``).
43+
44+
Returns:
45+
A decorator that validates the key and returns the function unchanged.
46+
47+
Raises:
48+
AgentDecoratorError: If the key is empty or whitespace-only.
49+
50+
Example::
51+
52+
@prompt_section(
53+
key="prompts.identity",
54+
label="Agent Identity",
55+
description="Core identity and role definition",
56+
validation={"format": "text", "max_length": 500},
57+
)
58+
def get_identity_prompt() -> str:
59+
return "You are an expert assistant..."
60+
"""
61+
_validate_key(key)
62+
63+
def decorator(fn: Callable[[], str]) -> Callable[[], str]:
64+
return fn
65+
66+
return decorator
67+
68+
69+
def agent_config(
70+
key: str,
71+
label: str,
72+
description: str,
73+
) -> Callable:
74+
"""Expose an agent configuration value for editing.
75+
76+
Args:
77+
key: Unique identifier (e.g. ``"config.temperature"``).
78+
label: Human-readable label.
79+
description: Help text.
80+
81+
Returns:
82+
A decorator that validates the key and returns the function unchanged.
83+
84+
Raises:
85+
AgentDecoratorError: If the key is empty or whitespace-only.
86+
87+
Example::
88+
89+
@agent_config(
90+
key="config.temperature",
91+
label="Temperature",
92+
description="The temperature setting for the language model",
93+
)
94+
def get_temperature() -> float:
95+
return 0.7
96+
"""
97+
_validate_key(key)
98+
99+
def decorator(fn: Callable) -> Callable:
100+
return fn
101+
102+
return decorator
103+
104+
105+
def agent_model(
106+
key: str,
107+
label: str,
108+
description: str = "",
109+
) -> Callable:
110+
"""Expose an agent model selection for editing.
111+
112+
Args:
113+
key: Unique identifier (e.g. ``"config.model"``).
114+
label: Human-readable label.
115+
description: Help text (optional).
116+
117+
Returns:
118+
A decorator that validates the key and returns the function unchanged.
119+
120+
Raises:
121+
AgentDecoratorError: If the key is empty or whitespace-only.
122+
123+
Example::
124+
125+
@agent_model(
126+
key="config.model",
127+
label="LLM Model",
128+
description="The language model powering this agent",
129+
)
130+
def get_model_name() -> str:
131+
return "sap/gpt-4o"
132+
"""
133+
_validate_key(key)
134+
135+
def decorator(fn: Callable) -> Callable:
136+
return fn
137+
138+
return decorator
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"""Custom exceptions for SAP Agent Decorators."""
2+
3+
4+
class AgentDecoratorError(Exception):
5+
"""Base exception for agent decorator operations."""
6+
7+
pass

src/sap_cloud_sdk/agent_decorators/py.typed

Whitespace-only changes.

0 commit comments

Comments
 (0)