You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Reviews a PR against 23 criteria across 6 sections. Run from the root of the `cloud-sdk-python` repository.
10
+
Reviews a PR against 25 criteria across 6 sections. Run from the root of the `cloud-sdk-python` repository.
11
11
12
12
---
13
13
@@ -172,6 +172,16 @@ New list/query operations: encapsulate pagination params like existing modules (
172
172
**D5: Telemetry instrumentation**
173
173
New client methods: `@record_metrics(Module.X, Operation.Y)` from `core/telemetry`. New module: constant added to `core/telemetry/module.py` and operations to `core/telemetry/operation.py`. If module is called by other SDK modules: `_telemetry_source: Optional[Module] = None` param present.
174
174
175
+
**D6: Multi-tenancy support**
176
+
Multi-tenancy is a cross-cutting concern for most BTP applications. For new service modules, consider the full scope of multi-tenancy — not just token routing, but also provisioning and tenant isolation:
177
+
178
+
-**Provisioning:** Does the service require a subscription or onboarding step per tenant? Does the module need to support tenant lifecycle callbacks (subscribe/unsubscribe)?
179
+
-**Tenant isolation:** Is data or configuration isolated per tenant at the service level? Does the module enforce or expose tenant boundaries correctly?
180
+
-**Auth/routing:** Does the module need to route requests to a subscriber tenant context (e.g., XSUAA subdomain replacement, IAS `app_tid`, or Destination Service routing)?
181
+
-**Infrastructure:** Is there any infrastructure work required (e.g., new service binding fields, SPII fragments, Subscription Manager integration)?
182
+
183
+
This is a **nice-to-have** (⚠️ if absent, not ❌), but must be a conscious decision either way — the `user-guide.md` must document whether support is present, planned, or intentionally out of scope (see E2a).
184
+
175
185
---
176
186
177
187
### Section E: Tests & Documentation
@@ -182,6 +192,15 @@ Every changed `src/` file → corresponding change in `tests/`. Unit: `tests/[mo
182
192
**E2: Documentation quality**
183
193
New modules: `user-guide.md` with overview, quick start, config examples, API examples, troubleshooting. Changed public APIs: docstrings updated (Google/NumPy style: `Args:`, `Returns:`, `Raises:`). Sub-audience features not mixed into the general user guide.
184
194
195
+
**E2a: Multi-tenancy documentation**
196
+
Every new or modified `user-guide.md` must contain a `## Multi-tenancy` section with all four fields:
197
+
-**Supported:** Yes / No / Not yet / N/A
198
+
-**Authentication:** XSUAA / IAS / Other / —
199
+
-**How to use:** explanation (or "Not applicable")
200
+
-**Further reading:** link(s) or "—"
201
+
202
+
If the module exposes XSUAA or IAS authentication, the section must describe the actual mechanism (e.g., `access_strategy` param, `tenant` param, token URL replacement). A placeholder or missing section → ⚠️. If the module is a new service module with no section at all → ❌.
Copy file name to clipboardExpand all lines: src/sap_cloud_sdk/agent_memory/user-guide.md
+14-62Lines changed: 14 additions & 62 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -23,10 +23,6 @@ plain text, and the service makes it searchable by meaning.
23
23
-[`agent_id`](#agent_id)
24
24
-[`invoker_id`](#invoker_id)
25
25
-[Multitenancy](#multitenancy)
26
-
-[AccessStrategy](#accessstrategy)
27
-
-[Configuring at client level](#configuring-at-client-level)
28
-
-[SUBSCRIBER (default)](#subscriber-default)
29
-
-[PROVIDER](#provider)
30
26
-[Semantic Search: A Brief Primer](#semantic-search-a-brief-primer)
31
27
-[Memories](#memories)
32
28
-[Create a Memory](#create-a-memory)
@@ -172,64 +168,20 @@ across create, read, and search calls is the implementer's responsibility.
172
168
173
169
## Multitenancy
174
170
175
-
The Agent Memory service runs in a multi-tenant BTP environment. By default, every API
176
-
call uses a **subscriber-scoped token** — meaning data is isolated to the subscriber tenant
177
-
that your application serves. You control this behaviour with the `access_strategy` and
178
-
`tenant` keyword arguments available on every client method.
171
+
-**Supported:** Yes
172
+
-**Authentication:** XSUAA
173
+
-**How to use:** Pass `access_strategy` and `tenant` to `create_client()`. The strategy controls whether calls use a subscriber-scoped or provider-scoped XSUAA token. Every method on the client inherits the strategy set at construction time.
> `PROVIDER` strategy provides **no tenant isolation**, the provider token grants access to data in the provider subaccount. Only use this strategy for provider-owned operations (e.g., admin tasks, shared datasets). Never use it to serve subscriber-specific data.
182
+
-**Further reading:** N/A
209
183
210
-
### SUBSCRIBER (default)
211
184
212
-
Configure a subscriber tenant at client creation. All calls will use that tenant context.
> `PROVIDER` provides **no tenant isolation** — the provider token grants access to data across all subscriber tenants Only use this strategy for provider-owned operations (e.g., admin tasks, shared datasets). Never use it to serve subscriber-specific data.
233
185
234
186
## Semantic Search: A Brief Primer
235
187
@@ -568,10 +520,10 @@ See the [Content and metadata filtering](#content-and-metadata-filtering) note u
Copy file name to clipboardExpand all lines: src/sap_cloud_sdk/agentgateway/user-guide.md
+16-7Lines changed: 16 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -125,7 +125,7 @@ mcp_tool_to_langchain(
125
125
The converter maps each property's JSON Schema `"type"` to the corresponding Python type so Pydantic validates and forwards the correct native type to the MCP server:
126
126
127
127
| JSON Schema type | Python type |
128
-
|------------------|-------------|
128
+
|----------------|-----------|
129
129
|`"string"`|`str`|
130
130
|`"integer"`|`int`|
131
131
|`"number"`|`float`|
@@ -149,12 +149,21 @@ The SDK automatically detects the agent type based on the presence of a credenti
149
149
150
150
The SDK discovers resources via BTP Destination Service fragments filtered by the `sap-managed-runtime-type` label:
151
151
152
-
| Label value | Resource |
153
-
|---|---|
154
-
|`agw.mcp.server`| MCP tool server — `URL` property points to the MCP endpoint |
155
-
|`agw.a2a.server`| A2A agent — `URL` property is the agent base URL; ORD ID is extracted from the second-to-last URL path segment |
156
-
|`subscriber.ias`| IAS credential fragment for system-scoped token acquisition |
157
-
|`subscriber.ias.user`| IAS credential fragment for user-scoped token exchange |
Copy file name to clipboardExpand all lines: src/sap_cloud_sdk/aicore/user-guide.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -390,6 +390,14 @@ set_aicore_config()
390
390
391
391
---
392
392
393
+
## Multi-tenancy
394
+
395
+
-**Supported:** No
396
+
-**Authentication:** XSUAA (written to litellm environment variables)
397
+
-**How to use:** Not supported. This module is a process-level bootstrap that writes XSUAA credentials to environment variables consumed by litellm. Multi-tenant routing is out of scope at this layer.
398
+
-**Further reading:**
399
+
-[SAP AI Core — SAP Help Portal](https://help.sap.com/docs/sap-ai-core)
-**How to use:** Tenant identity is expressed as an event-level field inside each logged event, not at the authentication layer. The provider always authenticates with its own XSUAA token. Pass `Tenant.SUBSCRIBER` or `Tenant.PROVIDER` when constructing events.
336
+
-**Further reading:**
337
+
-[SAP Audit Log Service — SAP Help Portal](https://help.sap.com/docs/btp/sap-business-technology-platform/audit-log-service)
338
+
331
339
## Error Handling
332
340
333
341
Always handle exceptions when logging audit events:
> **Tip:** When using `StarletteIASTelemetryMiddleware` (see [Automatic tenant and user injection](#automatic-tenant-and-user-injection)), `common.tenant_id` and `common.user_initiator_id` are filled automatically from the incoming IAS JWT. You only need to set them explicitly if you want to override the values from the token.
172
+
171
173
### Step 4: Send the Event
172
174
173
175
**Binary protobuf:**
@@ -274,6 +276,14 @@ with create_client(
274
276
275
277
---
276
278
279
+
## Multi-tenancy
280
+
281
+
-**Supported:** N/A at auth level
282
+
-**Authentication:** None (uses Destination Service / SPII for transport)
283
+
-**How to use:** Tenant identity is embedded in each event payload via the `tenant_id` field. Transport and auth are handled by the Destination Service / SPII. This module is only available through SAP for ME.
284
+
-**Further reading:**
285
+
-[SAP Audit Log Service — SAP Help Portal](https://help.sap.com/docs/btp/sap-business-technology-platform/audit-log-service)
286
+
277
287
## Validation
278
288
279
289
Events are validated against protobuf constraints using `protovalidate` before sending. A `ValueError` is raised if:
@@ -284,6 +294,55 @@ Events are validated against protobuf constraints using `protovalidate` before s
284
294
285
295
---
286
296
297
+
## Automatic tenant and user injection
298
+
299
+
When `StarletteIASTelemetryMiddleware` is registered on your app, it parses the
300
+
incoming `Authorization: Bearer <token>` header on every request and stores the
301
+
IAS claims in the current async context.
302
+
303
+
`AuditClient.send()` reads that context automatically before validation and
304
+
back-fills two fields on the event's `common` block — only if they are not
305
+
already set by the caller:
306
+
307
+
| Field populated | IAS claim used |
308
+
|---|---|
309
+
|`common.tenant_id`|`app_tid`|
310
+
|`common.user_initiator_id`|`user_uuid`|
311
+
312
+
### Setup
313
+
314
+
Register the middleware once when your app starts:
315
+
316
+
```python
317
+
from sap_cloud_sdk.core.telemetry import auto_instrument
318
+
from sap_cloud_sdk.core.telemetry.middleware import StarletteIASTelemetryMiddleware
0 commit comments