Skip to content

Commit 7091daf

Browse files
committed
docs(aicore): add Credential Rotation section to user-guide
Documents watch_aicore_config, patch_litellm_for_credential_rotation, and the recommended startup pattern for LangGraph/ChatLiteLLM agents.
1 parent dc4bd6e commit 7091daf

1 file changed

Lines changed: 75 additions & 0 deletions

File tree

src/sap_cloud_sdk/aicore/user-guide.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,81 @@ set_aicore_config(instance_name="aicore-production")
4747

4848
---
4949

50+
## Credential Rotation
51+
52+
BTP rotates AI Core service binding credentials automatically. The SDK
53+
handles this transparently — no pod restart required.
54+
55+
### Reactive reload (completion wrapper)
56+
57+
`sap_cloud_sdk.aicore.completion` / `acompletion` catch `AuthenticationError`
58+
(HTTP 401), reload credentials via `set_aicore_config()`, and retry the call
59+
once. The caller never sees the error.
60+
61+
```python
62+
from sap_cloud_sdk.aicore import completion, set_aicore_config
63+
64+
set_aicore_config()
65+
66+
# 401s are retried transparently — no extra code needed
67+
response = completion(model="sap/anthropic--claude-4.5-sonnet", messages=[...])
68+
```
69+
70+
### Proactive reload (recommended for all agents)
71+
72+
`watch_aicore_config()` starts a daemon thread that polls the mounted secret
73+
directory every 60 seconds. When the directory mtime changes (Kubernetes
74+
performs an atomic symlink swap on rotation), it calls `set_aicore_config()`
75+
before the cached OAuth token expires — so agents never see a 401 at all.
76+
77+
```python
78+
import threading
79+
from sap_cloud_sdk.aicore import set_aicore_config, watch_aicore_config
80+
81+
set_aicore_config() # load credentials at startup
82+
watch_aicore_config() # proactive reload on secret rotation
83+
84+
# Optional: stop cleanly at shutdown
85+
_stop = threading.Event()
86+
watch_aicore_config(stop_event=_stop)
87+
# at shutdown: _stop.set()
88+
```
89+
90+
### LangGraph / ChatLiteLLM agents
91+
92+
`ChatLiteLLM` (used in LangGraph agent templates) calls `litellm.completion`
93+
directly, bypassing the SDK's reactive handler. Two options:
94+
95+
**Option A — proactive watcher only (recommended, one line):**
96+
97+
```python
98+
from sap_cloud_sdk.aicore import set_aicore_config, watch_aicore_config
99+
100+
set_aicore_config()
101+
watch_aicore_config() # ADD THIS — no other changes needed
102+
```
103+
104+
**Option B — also add reactive reload for ChatLiteLLM:**
105+
106+
```python
107+
from sap_cloud_sdk.aicore import (
108+
set_aicore_config,
109+
patch_litellm_for_credential_rotation,
110+
watch_aicore_config,
111+
)
112+
113+
set_aicore_config()
114+
patch_litellm_for_credential_rotation() # patches litellm.completion globally
115+
watch_aicore_config()
116+
```
117+
118+
`patch_litellm_for_credential_rotation()` wraps `litellm.completion` /
119+
`litellm.acompletion` globally so every caller in the process — including
120+
`ChatLiteLLM` — gets transparent 401 reload. Idempotent; call it once at
121+
startup.
122+
123+
---
124+
50125
## What It Does
51126

52127
The `set_aicore_config()` function:

0 commit comments

Comments
 (0)