deepintshield 2.3.0__tar.gz → 2.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {deepintshield-2.3.0/src/deepintshield.egg-info → deepintshield-2.4.0}/PKG-INFO +33 -33
- {deepintshield-2.3.0 → deepintshield-2.4.0}/README.md +32 -32
- {deepintshield-2.3.0 → deepintshield-2.4.0}/pyproject.toml +1 -1
- deepintshield-2.4.0/src/deepintshield/version.py +1 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0/src/deepintshield.egg-info}/PKG-INFO +33 -33
- deepintshield-2.3.0/src/deepintshield/version.py +0 -1
- {deepintshield-2.3.0 → deepintshield-2.4.0}/LICENSE +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/setup.cfg +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/__init__.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/_gemini_cache.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/_prompt_cache.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agent.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/__init__.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/credentials/__init__.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/credentials/base.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/credentials/entra.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/credentials/oidc.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/credentials/zeroid.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/decorators.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/enforcement.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/engine.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/errors.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/gate.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/__init__.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/_common.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/autogen.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/crewai.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/langchain.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/langgraph.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/litellm.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/llamaindex.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/openai_agents.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/pydanticai.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/manifest.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/obligations.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/surface.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/types.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/client.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/config.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/errors.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/__init__.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/autogen.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/crewai.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/langgraph.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/llamaindex.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/openai_agents.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/pydanticai.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/__init__.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/adapters/__init__.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/adapters/anthropic.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/adapters/langchain.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/adapters/openai.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/client.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/tool.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/__init__.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/anthropic.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/bedrock.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/genai.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/langchain.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/langgraph.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/litellm.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/openai.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/pydanticai.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/rag.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/transport.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/types.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield.egg-info/SOURCES.txt +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield.egg-info/dependency_links.txt +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield.egg-info/requires.txt +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield.egg-info/top_level.txt +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_agent.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_agentic.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_agentic_langchain.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_client.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_config.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_errors.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_gemini_cache.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_prompt_cache.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_providers.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_rag.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_rag_guard.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_transport.py +0 -0
- {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepintshield
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: Unified Python SDK for routing chat, RAG, agentic tool-gating, identity, and MCP traffic through DeepintShield — drop-in across the top agentic frameworks.
|
|
5
5
|
Author: DeepintShield
|
|
6
6
|
License: Apache-2.0
|
|
@@ -71,7 +71,7 @@ Dynamic: license-file
|
|
|
71
71
|
|
|
72
72
|
# deepintshield
|
|
73
73
|
|
|
74
|
-
Unified Python SDK for DeepintShield
|
|
74
|
+
Unified Python SDK for DeepintShield - one import, any provider, any agent framework.
|
|
75
75
|
|
|
76
76
|
`deepintshield` lets you keep writing idiomatic OpenAI / Anthropic / Bedrock /
|
|
77
77
|
Google GenAI code **and** native agent-framework code (LangGraph, CrewAI,
|
|
@@ -79,20 +79,20 @@ OpenAI Agents SDK, LlamaIndex, AutoGen, PydanticAI) while automatically routing
|
|
|
79
79
|
traffic through the DeepintShield gateway for guardrails, RAG filtering, agentic
|
|
80
80
|
tool control, and agent identity.
|
|
81
81
|
|
|
82
|
-
You pass **only two things
|
|
83
|
-
the Entra / ZeroID / OIDC identity binding, tenant, scopes, and policy
|
|
82
|
+
You pass **only two things - a virtual key and a base URL.** Everything else -
|
|
83
|
+
the Entra / ZeroID / OIDC identity binding, tenant, scopes, and policy - is
|
|
84
84
|
discovered from the gateway automatically. No identity GUIDs ever appear in your
|
|
85
85
|
code.
|
|
86
86
|
|
|
87
87
|
Protection comes in two layers:
|
|
88
88
|
|
|
89
|
-
- **Transparent**
|
|
89
|
+
- **Transparent** - point any framework's *native* client at the gateway
|
|
90
90
|
(`base_url` + a one-line header injector). Chat, embeddings, input/output and
|
|
91
91
|
RAG-prompt guardrails, observability and identity all run server-side with
|
|
92
92
|
**zero changes** to your agent code. Works for Python frameworks *and* any
|
|
93
93
|
OpenAI-compatible platform (n8n, Flowise, Dify, raw HTTP).
|
|
94
|
-
- **Enforcement**
|
|
95
|
-
MASK / human approval) and **chunk-level RAG filtering**
|
|
94
|
+
- **Enforcement** - one wrapping line adds local **tool gating** (DENY /
|
|
95
|
+
MASK / human approval) and **chunk-level RAG filtering** - the parts that
|
|
96
96
|
physically can't be done at the wire because the tool runs in your process.
|
|
97
97
|
|
|
98
98
|
Traffic defaults to **`https://app.deepintshield.com`**. Override the gateway
|
|
@@ -126,7 +126,7 @@ pip install 'deepintshield[all]' # everything
|
|
|
126
126
|
|
|
127
127
|
```bash
|
|
128
128
|
export DEEPINTSHIELD_VIRTUAL_KEY="sk-..."
|
|
129
|
-
# Optional
|
|
129
|
+
# Optional - point at a self-hosted or staging gateway.
|
|
130
130
|
export DEEPINTSHIELD_BASE_URL="https://gateway.example.com"
|
|
131
131
|
```
|
|
132
132
|
|
|
@@ -251,7 +251,7 @@ allowed, raw = shield.rag.filter(query="What's the badge rule?", chunks=chunks)
|
|
|
251
251
|
### Guard a framework retriever (post-retrieval, one line)
|
|
252
252
|
|
|
253
253
|
Wrap any LangChain / LlamaIndex retriever so unauthorised chunks are dropped
|
|
254
|
-
*after* retrieval and *before* they reach the LLM
|
|
254
|
+
*after* retrieval and *before* they reach the LLM - ACL/provenance filtering
|
|
255
255
|
your retriever can't do itself:
|
|
256
256
|
|
|
257
257
|
```python
|
|
@@ -269,7 +269,7 @@ embedder.embed_query("text") # raises if the gatewa
|
|
|
269
269
|
```
|
|
270
270
|
|
|
271
271
|
> If you obtain your embedder from a framework binder (below), input-side
|
|
272
|
-
> screening already happens server-side
|
|
272
|
+
> screening already happens server-side - `guard_embedder` is for embedders you
|
|
273
273
|
> don't route through the gateway.
|
|
274
274
|
|
|
275
275
|
---
|
|
@@ -292,7 +292,7 @@ shield.autogen().model_client("gpt-4o-mini") # OpenAIChatCompletionClient
|
|
|
292
292
|
shield.pydanticai().model("gpt-4o-mini")
|
|
293
293
|
```
|
|
294
294
|
|
|
295
|
-
Framework-agnostic primitives
|
|
295
|
+
Framework-agnostic primitives - wire any SDK, in any language-compatible
|
|
296
296
|
client, by hand:
|
|
297
297
|
|
|
298
298
|
```python
|
|
@@ -302,23 +302,23 @@ headers = shield.create_headers(provider="anthropic") # Portkey-style header i
|
|
|
302
302
|
```
|
|
303
303
|
|
|
304
304
|
> **Universal:** anything that speaks OpenAI-compatible HTTP gets transparent
|
|
305
|
-
> protection with *zero code*
|
|
305
|
+
> protection with *zero code* - set the Base URL to `shield.endpoint("openai")`
|
|
306
306
|
> and the key to your VK. That covers n8n, Flowise, Dify and raw HTTP, not just
|
|
307
307
|
> Python.
|
|
308
308
|
|
|
309
309
|
## Agentic tool enforcement
|
|
310
310
|
|
|
311
311
|
The part a base URL can't do: gate **local** tool execution. Each gated call
|
|
312
|
-
runs `decide()` first and the verdict maps to a Python outcome
|
|
312
|
+
runs `decide()` first and the verdict maps to a Python outcome - `ALLOW` runs
|
|
313
313
|
the body, `MASK` redacts PII kwargs, `REQUIRE_APPROVAL` blocks for a human, and
|
|
314
314
|
`DENY` raises `GuardrailDenied`.
|
|
315
315
|
|
|
316
|
-
### Zero extra code
|
|
316
|
+
### Zero extra code - enforcement is automatic and non-bypassable
|
|
317
317
|
|
|
318
318
|
The moment you construct `DeepintShield(...)`, the SDK installs guards for every
|
|
319
319
|
agent framework you've imported (LangGraph, CrewAI, LlamaIndex, AutoGen,
|
|
320
320
|
PydanticAI, the OpenAI Agents SDK, LiteLLM). After that, **compiling / building
|
|
321
|
-
an agent yields an already-governed object**
|
|
321
|
+
an agent yields an already-governed object** - you can't forget to gate it and
|
|
322
322
|
you can't bypass it by invoking the un-governed one (there isn't one).
|
|
323
323
|
|
|
324
324
|
```python
|
|
@@ -334,7 +334,7 @@ g = StateGraph(State)
|
|
|
334
334
|
g.add_node("read_step", crm_read)
|
|
335
335
|
g.add_node("admin_step", admin_grant)
|
|
336
336
|
...
|
|
337
|
-
app = g.compile() # auto-governed
|
|
337
|
+
app = g.compile() # auto-governed - every node now gated by the PDP
|
|
338
338
|
|
|
339
339
|
app.invoke({...}) # a DENY raises GuardrailDenied before the node runs
|
|
340
340
|
```
|
|
@@ -345,32 +345,32 @@ If you import a framework *after* building the client, call
|
|
|
345
345
|
> **Security follows the implementation, not the label.** Each node/tool is
|
|
346
346
|
> governed by its **function name** (`crm_read`), not the node label
|
|
347
347
|
> (`read_step`), and the decision is bound to a fingerprint of the function's
|
|
348
|
-
> **source**
|
|
348
|
+
> **source** - so editing the body is detected and policies target `crm_read`.
|
|
349
349
|
>
|
|
350
350
|
> **Trust boundary:** these client guards are cooperative defense-in-depth. A
|
|
351
351
|
> determined process can un-patch them or call a tool's raw function, so the
|
|
352
352
|
> gateway (MCP / LLM in the call path) remains the authoritative boundary.
|
|
353
353
|
|
|
354
|
-
### `govern()`
|
|
354
|
+
### `govern()` - register + threat-scan + instrument (explicit, idempotent)
|
|
355
355
|
|
|
356
356
|
`govern()` does everything the auto-guard does, explicitly: it **describes** the
|
|
357
357
|
agent's declared tool surface, **registers** that blueprint with the server
|
|
358
|
-
(which **threat-scans each tool's source** for RCE / shell-out / exfiltration
|
|
359
|
-
OWASP Agentic **T11 / T17**
|
|
358
|
+
(which **threat-scans each tool's source** for RCE / shell-out / exfiltration -
|
|
359
|
+
OWASP Agentic **T11 / T17** - server-side, ZDR), and **instruments** every call.
|
|
360
360
|
|
|
361
361
|
```python
|
|
362
|
-
app = shield.agentic.govern(app) # idempotent
|
|
362
|
+
app = shield.agentic.govern(app) # idempotent - safe alongside the auto-guard
|
|
363
363
|
```
|
|
364
364
|
|
|
365
365
|
A tool whose source scans malicious is flagged (Agentic → Findings) and, when
|
|
366
|
-
the workspace enables **Enforce code threat** (Rollout), denied
|
|
366
|
+
the workspace enables **Enforce code threat** (Rollout), denied - even if a
|
|
367
367
|
policy would otherwise allow it. A tool called but never declared shows up as
|
|
368
368
|
**ASI04 drift** under Agentic → Discovery.
|
|
369
369
|
|
|
370
|
-
### `guard()`
|
|
370
|
+
### `guard()` - LangChain callback / in-place instrument
|
|
371
371
|
|
|
372
372
|
`shield.agentic.guard()` (no argument) returns a native LangChain callback
|
|
373
|
-
handler; attaching it once gates *every* tool the agent calls
|
|
373
|
+
handler; attaching it once gates *every* tool the agent calls - the framework
|
|
374
374
|
supplies the tool name and the **gateway resolves the tier, policy, recovery
|
|
375
375
|
cost and identity server-side**.
|
|
376
376
|
|
|
@@ -382,7 +382,7 @@ agent_executor.invoke({"input": "…"}, config={"callbacks": [guard]})
|
|
|
382
382
|
`guard(target)` auto-detects and instruments a framework object in place:
|
|
383
383
|
|
|
384
384
|
```python
|
|
385
|
-
shield.agentic.guard(compiled_graph) # LangGraph
|
|
385
|
+
shield.agentic.guard(compiled_graph) # LangGraph - gate every tool node
|
|
386
386
|
shield.agentic.guard(crewai_tools) # CrewAI BaseTools
|
|
387
387
|
shield.agentic.guard(openai_agent) # OpenAI Agents FunctionTools
|
|
388
388
|
shield.agentic.guard(pydantic_agent) # PydanticAI agent
|
|
@@ -435,7 +435,7 @@ When the virtual key is bound to an identity provider, the SDK auto-discovers
|
|
|
435
435
|
the binding (`GET /api/agentic-security/vk-credential-info`), selects the right
|
|
436
436
|
credential (Entra Agent ID FIC / ZeroID RFC 8693 / generic OIDC), and attaches a
|
|
437
437
|
fresh `X-Agent-Token` on every decision. On Azure compute the Managed Identity
|
|
438
|
-
is detected automatically
|
|
438
|
+
is detected automatically - **no GUIDs, authority, or scopes in your code.**
|
|
439
439
|
|
|
440
440
|
```python
|
|
441
441
|
info = shield.agentic.credential_info # ops visibility into the binding
|
|
@@ -473,7 +473,7 @@ app = graph.compile()
|
|
|
473
473
|
## Multimodal guardrails (transparent)
|
|
474
474
|
|
|
475
475
|
Image generation, image edits, audio (TTS / transcription), video, embedding and
|
|
476
|
-
rerank requests are guarded **at the gateway**
|
|
476
|
+
rerank requests are guarded **at the gateway** - no SDK changes and no extra code.
|
|
477
477
|
Keep using the native provider SDKs through DeepIntShield; when the operator
|
|
478
478
|
enables `GUARDRAILS_MULTIMODAL`, the gateway evaluates the text these requests
|
|
479
479
|
already carry (image/TTS/video prompts, transcripts) and the binary artifacts
|
|
@@ -482,7 +482,7 @@ themselves, blocking or flagging per your policies.
|
|
|
482
482
|
```python
|
|
483
483
|
client = shield.openai()
|
|
484
484
|
|
|
485
|
-
# Guarded automatically
|
|
485
|
+
# Guarded automatically - the image prompt is evaluated before generation.
|
|
486
486
|
img = client.images.generate(model="gpt-image-1", prompt="a serene mountain lake")
|
|
487
487
|
|
|
488
488
|
# A blocked prompt surfaces as the provider SDK's normal HTTP error:
|
|
@@ -501,7 +501,7 @@ enforcing (`sync`) or observe-only (`shadow`).
|
|
|
501
501
|
|
|
502
502
|
## MCP
|
|
503
503
|
|
|
504
|
-
Generic MCP support
|
|
504
|
+
Generic MCP support - works with any server connected to your DeepintShield
|
|
505
505
|
gateway. No per-server SDK code; the same `Tool` / `MCPClient` API serves
|
|
506
506
|
DeepWiki, Context7, GitHub MCP, an internal one, and so on.
|
|
507
507
|
|
|
@@ -596,7 +596,7 @@ print(AgentExecutor(agent=agent, tools=mcp_tools).invoke(
|
|
|
596
596
|
)["output"])
|
|
597
597
|
```
|
|
598
598
|
|
|
599
|
-
LangGraph reuses the same `mcp_tools` list
|
|
599
|
+
LangGraph reuses the same `mcp_tools` list - drop them into a `ToolNode`.
|
|
600
600
|
|
|
601
601
|
---
|
|
602
602
|
|
|
@@ -605,16 +605,16 @@ LangGraph reuses the same `mcp_tools` list — drop them into a `ToolNode`.
|
|
|
605
605
|
The SDK automatically participates in the gateway's two cost-reduction layers
|
|
606
606
|
(both controlled by workspace switches under **Cost Optimization**):
|
|
607
607
|
|
|
608
|
-
- **Provider prompt caching**
|
|
608
|
+
- **Provider prompt caching** - every chat client returned by `shield.openai()`,
|
|
609
609
|
`shield.anthropic()`, etc. ships an `httpx` request hook that injects
|
|
610
610
|
Anthropic `cache_control` markers and an OpenAI `prompt_cache_key` so the
|
|
611
611
|
provider reuses KV state for the static prompt prefix. Cached tokens come
|
|
612
612
|
back at the provider's reduced rate (50% off OpenAI, 90% off Anthropic).
|
|
613
|
-
- **Gemini context caching**
|
|
613
|
+
- **Gemini context caching** - opt in with `shield.genai_cached()` (drop-in
|
|
614
614
|
for `shield.genai()`). The wrapper manages the `cachedContents` resource
|
|
615
615
|
lifecycle behind the scenes; the first call with a new static prefix runs
|
|
616
616
|
normally and the next call within the TTL window reuses the cache.
|
|
617
|
-
- **Semantic caching**
|
|
617
|
+
- **Semantic caching** - runs on the gateway; short-circuits requests whose
|
|
618
618
|
embeddings match a previous response within the configured similarity
|
|
619
619
|
threshold. The SDK doesn't need any code change to benefit; results flow
|
|
620
620
|
back through the normal API.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# deepintshield
|
|
2
2
|
|
|
3
|
-
Unified Python SDK for DeepintShield
|
|
3
|
+
Unified Python SDK for DeepintShield - one import, any provider, any agent framework.
|
|
4
4
|
|
|
5
5
|
`deepintshield` lets you keep writing idiomatic OpenAI / Anthropic / Bedrock /
|
|
6
6
|
Google GenAI code **and** native agent-framework code (LangGraph, CrewAI,
|
|
@@ -8,20 +8,20 @@ OpenAI Agents SDK, LlamaIndex, AutoGen, PydanticAI) while automatically routing
|
|
|
8
8
|
traffic through the DeepintShield gateway for guardrails, RAG filtering, agentic
|
|
9
9
|
tool control, and agent identity.
|
|
10
10
|
|
|
11
|
-
You pass **only two things
|
|
12
|
-
the Entra / ZeroID / OIDC identity binding, tenant, scopes, and policy
|
|
11
|
+
You pass **only two things - a virtual key and a base URL.** Everything else -
|
|
12
|
+
the Entra / ZeroID / OIDC identity binding, tenant, scopes, and policy - is
|
|
13
13
|
discovered from the gateway automatically. No identity GUIDs ever appear in your
|
|
14
14
|
code.
|
|
15
15
|
|
|
16
16
|
Protection comes in two layers:
|
|
17
17
|
|
|
18
|
-
- **Transparent**
|
|
18
|
+
- **Transparent** - point any framework's *native* client at the gateway
|
|
19
19
|
(`base_url` + a one-line header injector). Chat, embeddings, input/output and
|
|
20
20
|
RAG-prompt guardrails, observability and identity all run server-side with
|
|
21
21
|
**zero changes** to your agent code. Works for Python frameworks *and* any
|
|
22
22
|
OpenAI-compatible platform (n8n, Flowise, Dify, raw HTTP).
|
|
23
|
-
- **Enforcement**
|
|
24
|
-
MASK / human approval) and **chunk-level RAG filtering**
|
|
23
|
+
- **Enforcement** - one wrapping line adds local **tool gating** (DENY /
|
|
24
|
+
MASK / human approval) and **chunk-level RAG filtering** - the parts that
|
|
25
25
|
physically can't be done at the wire because the tool runs in your process.
|
|
26
26
|
|
|
27
27
|
Traffic defaults to **`https://app.deepintshield.com`**. Override the gateway
|
|
@@ -55,7 +55,7 @@ pip install 'deepintshield[all]' # everything
|
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
export DEEPINTSHIELD_VIRTUAL_KEY="sk-..."
|
|
58
|
-
# Optional
|
|
58
|
+
# Optional - point at a self-hosted or staging gateway.
|
|
59
59
|
export DEEPINTSHIELD_BASE_URL="https://gateway.example.com"
|
|
60
60
|
```
|
|
61
61
|
|
|
@@ -180,7 +180,7 @@ allowed, raw = shield.rag.filter(query="What's the badge rule?", chunks=chunks)
|
|
|
180
180
|
### Guard a framework retriever (post-retrieval, one line)
|
|
181
181
|
|
|
182
182
|
Wrap any LangChain / LlamaIndex retriever so unauthorised chunks are dropped
|
|
183
|
-
*after* retrieval and *before* they reach the LLM
|
|
183
|
+
*after* retrieval and *before* they reach the LLM - ACL/provenance filtering
|
|
184
184
|
your retriever can't do itself:
|
|
185
185
|
|
|
186
186
|
```python
|
|
@@ -198,7 +198,7 @@ embedder.embed_query("text") # raises if the gatewa
|
|
|
198
198
|
```
|
|
199
199
|
|
|
200
200
|
> If you obtain your embedder from a framework binder (below), input-side
|
|
201
|
-
> screening already happens server-side
|
|
201
|
+
> screening already happens server-side - `guard_embedder` is for embedders you
|
|
202
202
|
> don't route through the gateway.
|
|
203
203
|
|
|
204
204
|
---
|
|
@@ -221,7 +221,7 @@ shield.autogen().model_client("gpt-4o-mini") # OpenAIChatCompletionClient
|
|
|
221
221
|
shield.pydanticai().model("gpt-4o-mini")
|
|
222
222
|
```
|
|
223
223
|
|
|
224
|
-
Framework-agnostic primitives
|
|
224
|
+
Framework-agnostic primitives - wire any SDK, in any language-compatible
|
|
225
225
|
client, by hand:
|
|
226
226
|
|
|
227
227
|
```python
|
|
@@ -231,23 +231,23 @@ headers = shield.create_headers(provider="anthropic") # Portkey-style header i
|
|
|
231
231
|
```
|
|
232
232
|
|
|
233
233
|
> **Universal:** anything that speaks OpenAI-compatible HTTP gets transparent
|
|
234
|
-
> protection with *zero code*
|
|
234
|
+
> protection with *zero code* - set the Base URL to `shield.endpoint("openai")`
|
|
235
235
|
> and the key to your VK. That covers n8n, Flowise, Dify and raw HTTP, not just
|
|
236
236
|
> Python.
|
|
237
237
|
|
|
238
238
|
## Agentic tool enforcement
|
|
239
239
|
|
|
240
240
|
The part a base URL can't do: gate **local** tool execution. Each gated call
|
|
241
|
-
runs `decide()` first and the verdict maps to a Python outcome
|
|
241
|
+
runs `decide()` first and the verdict maps to a Python outcome - `ALLOW` runs
|
|
242
242
|
the body, `MASK` redacts PII kwargs, `REQUIRE_APPROVAL` blocks for a human, and
|
|
243
243
|
`DENY` raises `GuardrailDenied`.
|
|
244
244
|
|
|
245
|
-
### Zero extra code
|
|
245
|
+
### Zero extra code - enforcement is automatic and non-bypassable
|
|
246
246
|
|
|
247
247
|
The moment you construct `DeepintShield(...)`, the SDK installs guards for every
|
|
248
248
|
agent framework you've imported (LangGraph, CrewAI, LlamaIndex, AutoGen,
|
|
249
249
|
PydanticAI, the OpenAI Agents SDK, LiteLLM). After that, **compiling / building
|
|
250
|
-
an agent yields an already-governed object**
|
|
250
|
+
an agent yields an already-governed object** - you can't forget to gate it and
|
|
251
251
|
you can't bypass it by invoking the un-governed one (there isn't one).
|
|
252
252
|
|
|
253
253
|
```python
|
|
@@ -263,7 +263,7 @@ g = StateGraph(State)
|
|
|
263
263
|
g.add_node("read_step", crm_read)
|
|
264
264
|
g.add_node("admin_step", admin_grant)
|
|
265
265
|
...
|
|
266
|
-
app = g.compile() # auto-governed
|
|
266
|
+
app = g.compile() # auto-governed - every node now gated by the PDP
|
|
267
267
|
|
|
268
268
|
app.invoke({...}) # a DENY raises GuardrailDenied before the node runs
|
|
269
269
|
```
|
|
@@ -274,32 +274,32 @@ If you import a framework *after* building the client, call
|
|
|
274
274
|
> **Security follows the implementation, not the label.** Each node/tool is
|
|
275
275
|
> governed by its **function name** (`crm_read`), not the node label
|
|
276
276
|
> (`read_step`), and the decision is bound to a fingerprint of the function's
|
|
277
|
-
> **source**
|
|
277
|
+
> **source** - so editing the body is detected and policies target `crm_read`.
|
|
278
278
|
>
|
|
279
279
|
> **Trust boundary:** these client guards are cooperative defense-in-depth. A
|
|
280
280
|
> determined process can un-patch them or call a tool's raw function, so the
|
|
281
281
|
> gateway (MCP / LLM in the call path) remains the authoritative boundary.
|
|
282
282
|
|
|
283
|
-
### `govern()`
|
|
283
|
+
### `govern()` - register + threat-scan + instrument (explicit, idempotent)
|
|
284
284
|
|
|
285
285
|
`govern()` does everything the auto-guard does, explicitly: it **describes** the
|
|
286
286
|
agent's declared tool surface, **registers** that blueprint with the server
|
|
287
|
-
(which **threat-scans each tool's source** for RCE / shell-out / exfiltration
|
|
288
|
-
OWASP Agentic **T11 / T17**
|
|
287
|
+
(which **threat-scans each tool's source** for RCE / shell-out / exfiltration -
|
|
288
|
+
OWASP Agentic **T11 / T17** - server-side, ZDR), and **instruments** every call.
|
|
289
289
|
|
|
290
290
|
```python
|
|
291
|
-
app = shield.agentic.govern(app) # idempotent
|
|
291
|
+
app = shield.agentic.govern(app) # idempotent - safe alongside the auto-guard
|
|
292
292
|
```
|
|
293
293
|
|
|
294
294
|
A tool whose source scans malicious is flagged (Agentic → Findings) and, when
|
|
295
|
-
the workspace enables **Enforce code threat** (Rollout), denied
|
|
295
|
+
the workspace enables **Enforce code threat** (Rollout), denied - even if a
|
|
296
296
|
policy would otherwise allow it. A tool called but never declared shows up as
|
|
297
297
|
**ASI04 drift** under Agentic → Discovery.
|
|
298
298
|
|
|
299
|
-
### `guard()`
|
|
299
|
+
### `guard()` - LangChain callback / in-place instrument
|
|
300
300
|
|
|
301
301
|
`shield.agentic.guard()` (no argument) returns a native LangChain callback
|
|
302
|
-
handler; attaching it once gates *every* tool the agent calls
|
|
302
|
+
handler; attaching it once gates *every* tool the agent calls - the framework
|
|
303
303
|
supplies the tool name and the **gateway resolves the tier, policy, recovery
|
|
304
304
|
cost and identity server-side**.
|
|
305
305
|
|
|
@@ -311,7 +311,7 @@ agent_executor.invoke({"input": "…"}, config={"callbacks": [guard]})
|
|
|
311
311
|
`guard(target)` auto-detects and instruments a framework object in place:
|
|
312
312
|
|
|
313
313
|
```python
|
|
314
|
-
shield.agentic.guard(compiled_graph) # LangGraph
|
|
314
|
+
shield.agentic.guard(compiled_graph) # LangGraph - gate every tool node
|
|
315
315
|
shield.agentic.guard(crewai_tools) # CrewAI BaseTools
|
|
316
316
|
shield.agentic.guard(openai_agent) # OpenAI Agents FunctionTools
|
|
317
317
|
shield.agentic.guard(pydantic_agent) # PydanticAI agent
|
|
@@ -364,7 +364,7 @@ When the virtual key is bound to an identity provider, the SDK auto-discovers
|
|
|
364
364
|
the binding (`GET /api/agentic-security/vk-credential-info`), selects the right
|
|
365
365
|
credential (Entra Agent ID FIC / ZeroID RFC 8693 / generic OIDC), and attaches a
|
|
366
366
|
fresh `X-Agent-Token` on every decision. On Azure compute the Managed Identity
|
|
367
|
-
is detected automatically
|
|
367
|
+
is detected automatically - **no GUIDs, authority, or scopes in your code.**
|
|
368
368
|
|
|
369
369
|
```python
|
|
370
370
|
info = shield.agentic.credential_info # ops visibility into the binding
|
|
@@ -402,7 +402,7 @@ app = graph.compile()
|
|
|
402
402
|
## Multimodal guardrails (transparent)
|
|
403
403
|
|
|
404
404
|
Image generation, image edits, audio (TTS / transcription), video, embedding and
|
|
405
|
-
rerank requests are guarded **at the gateway**
|
|
405
|
+
rerank requests are guarded **at the gateway** - no SDK changes and no extra code.
|
|
406
406
|
Keep using the native provider SDKs through DeepIntShield; when the operator
|
|
407
407
|
enables `GUARDRAILS_MULTIMODAL`, the gateway evaluates the text these requests
|
|
408
408
|
already carry (image/TTS/video prompts, transcripts) and the binary artifacts
|
|
@@ -411,7 +411,7 @@ themselves, blocking or flagging per your policies.
|
|
|
411
411
|
```python
|
|
412
412
|
client = shield.openai()
|
|
413
413
|
|
|
414
|
-
# Guarded automatically
|
|
414
|
+
# Guarded automatically - the image prompt is evaluated before generation.
|
|
415
415
|
img = client.images.generate(model="gpt-image-1", prompt="a serene mountain lake")
|
|
416
416
|
|
|
417
417
|
# A blocked prompt surfaces as the provider SDK's normal HTTP error:
|
|
@@ -430,7 +430,7 @@ enforcing (`sync`) or observe-only (`shadow`).
|
|
|
430
430
|
|
|
431
431
|
## MCP
|
|
432
432
|
|
|
433
|
-
Generic MCP support
|
|
433
|
+
Generic MCP support - works with any server connected to your DeepintShield
|
|
434
434
|
gateway. No per-server SDK code; the same `Tool` / `MCPClient` API serves
|
|
435
435
|
DeepWiki, Context7, GitHub MCP, an internal one, and so on.
|
|
436
436
|
|
|
@@ -525,7 +525,7 @@ print(AgentExecutor(agent=agent, tools=mcp_tools).invoke(
|
|
|
525
525
|
)["output"])
|
|
526
526
|
```
|
|
527
527
|
|
|
528
|
-
LangGraph reuses the same `mcp_tools` list
|
|
528
|
+
LangGraph reuses the same `mcp_tools` list - drop them into a `ToolNode`.
|
|
529
529
|
|
|
530
530
|
---
|
|
531
531
|
|
|
@@ -534,16 +534,16 @@ LangGraph reuses the same `mcp_tools` list — drop them into a `ToolNode`.
|
|
|
534
534
|
The SDK automatically participates in the gateway's two cost-reduction layers
|
|
535
535
|
(both controlled by workspace switches under **Cost Optimization**):
|
|
536
536
|
|
|
537
|
-
- **Provider prompt caching**
|
|
537
|
+
- **Provider prompt caching** - every chat client returned by `shield.openai()`,
|
|
538
538
|
`shield.anthropic()`, etc. ships an `httpx` request hook that injects
|
|
539
539
|
Anthropic `cache_control` markers and an OpenAI `prompt_cache_key` so the
|
|
540
540
|
provider reuses KV state for the static prompt prefix. Cached tokens come
|
|
541
541
|
back at the provider's reduced rate (50% off OpenAI, 90% off Anthropic).
|
|
542
|
-
- **Gemini context caching**
|
|
542
|
+
- **Gemini context caching** - opt in with `shield.genai_cached()` (drop-in
|
|
543
543
|
for `shield.genai()`). The wrapper manages the `cachedContents` resource
|
|
544
544
|
lifecycle behind the scenes; the first call with a new static prefix runs
|
|
545
545
|
normally and the next call within the TTL window reuses the cache.
|
|
546
|
-
- **Semantic caching**
|
|
546
|
+
- **Semantic caching** - runs on the gateway; short-circuits requests whose
|
|
547
547
|
embeddings match a previous response within the configured similarity
|
|
548
548
|
threshold. The SDK doesn't need any code change to benefit; results flow
|
|
549
549
|
back through the normal API.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "deepintshield"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.4.0"
|
|
8
8
|
description = "Unified Python SDK for routing chat, RAG, agentic tool-gating, identity, and MCP traffic through DeepintShield — drop-in across the top agentic frameworks."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.4.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepintshield
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: Unified Python SDK for routing chat, RAG, agentic tool-gating, identity, and MCP traffic through DeepintShield — drop-in across the top agentic frameworks.
|
|
5
5
|
Author: DeepintShield
|
|
6
6
|
License: Apache-2.0
|
|
@@ -71,7 +71,7 @@ Dynamic: license-file
|
|
|
71
71
|
|
|
72
72
|
# deepintshield
|
|
73
73
|
|
|
74
|
-
Unified Python SDK for DeepintShield
|
|
74
|
+
Unified Python SDK for DeepintShield - one import, any provider, any agent framework.
|
|
75
75
|
|
|
76
76
|
`deepintshield` lets you keep writing idiomatic OpenAI / Anthropic / Bedrock /
|
|
77
77
|
Google GenAI code **and** native agent-framework code (LangGraph, CrewAI,
|
|
@@ -79,20 +79,20 @@ OpenAI Agents SDK, LlamaIndex, AutoGen, PydanticAI) while automatically routing
|
|
|
79
79
|
traffic through the DeepintShield gateway for guardrails, RAG filtering, agentic
|
|
80
80
|
tool control, and agent identity.
|
|
81
81
|
|
|
82
|
-
You pass **only two things
|
|
83
|
-
the Entra / ZeroID / OIDC identity binding, tenant, scopes, and policy
|
|
82
|
+
You pass **only two things - a virtual key and a base URL.** Everything else -
|
|
83
|
+
the Entra / ZeroID / OIDC identity binding, tenant, scopes, and policy - is
|
|
84
84
|
discovered from the gateway automatically. No identity GUIDs ever appear in your
|
|
85
85
|
code.
|
|
86
86
|
|
|
87
87
|
Protection comes in two layers:
|
|
88
88
|
|
|
89
|
-
- **Transparent**
|
|
89
|
+
- **Transparent** - point any framework's *native* client at the gateway
|
|
90
90
|
(`base_url` + a one-line header injector). Chat, embeddings, input/output and
|
|
91
91
|
RAG-prompt guardrails, observability and identity all run server-side with
|
|
92
92
|
**zero changes** to your agent code. Works for Python frameworks *and* any
|
|
93
93
|
OpenAI-compatible platform (n8n, Flowise, Dify, raw HTTP).
|
|
94
|
-
- **Enforcement**
|
|
95
|
-
MASK / human approval) and **chunk-level RAG filtering**
|
|
94
|
+
- **Enforcement** - one wrapping line adds local **tool gating** (DENY /
|
|
95
|
+
MASK / human approval) and **chunk-level RAG filtering** - the parts that
|
|
96
96
|
physically can't be done at the wire because the tool runs in your process.
|
|
97
97
|
|
|
98
98
|
Traffic defaults to **`https://app.deepintshield.com`**. Override the gateway
|
|
@@ -126,7 +126,7 @@ pip install 'deepintshield[all]' # everything
|
|
|
126
126
|
|
|
127
127
|
```bash
|
|
128
128
|
export DEEPINTSHIELD_VIRTUAL_KEY="sk-..."
|
|
129
|
-
# Optional
|
|
129
|
+
# Optional - point at a self-hosted or staging gateway.
|
|
130
130
|
export DEEPINTSHIELD_BASE_URL="https://gateway.example.com"
|
|
131
131
|
```
|
|
132
132
|
|
|
@@ -251,7 +251,7 @@ allowed, raw = shield.rag.filter(query="What's the badge rule?", chunks=chunks)
|
|
|
251
251
|
### Guard a framework retriever (post-retrieval, one line)
|
|
252
252
|
|
|
253
253
|
Wrap any LangChain / LlamaIndex retriever so unauthorised chunks are dropped
|
|
254
|
-
*after* retrieval and *before* they reach the LLM
|
|
254
|
+
*after* retrieval and *before* they reach the LLM - ACL/provenance filtering
|
|
255
255
|
your retriever can't do itself:
|
|
256
256
|
|
|
257
257
|
```python
|
|
@@ -269,7 +269,7 @@ embedder.embed_query("text") # raises if the gatewa
|
|
|
269
269
|
```
|
|
270
270
|
|
|
271
271
|
> If you obtain your embedder from a framework binder (below), input-side
|
|
272
|
-
> screening already happens server-side
|
|
272
|
+
> screening already happens server-side - `guard_embedder` is for embedders you
|
|
273
273
|
> don't route through the gateway.
|
|
274
274
|
|
|
275
275
|
---
|
|
@@ -292,7 +292,7 @@ shield.autogen().model_client("gpt-4o-mini") # OpenAIChatCompletionClient
|
|
|
292
292
|
shield.pydanticai().model("gpt-4o-mini")
|
|
293
293
|
```
|
|
294
294
|
|
|
295
|
-
Framework-agnostic primitives
|
|
295
|
+
Framework-agnostic primitives - wire any SDK, in any language-compatible
|
|
296
296
|
client, by hand:
|
|
297
297
|
|
|
298
298
|
```python
|
|
@@ -302,23 +302,23 @@ headers = shield.create_headers(provider="anthropic") # Portkey-style header i
|
|
|
302
302
|
```
|
|
303
303
|
|
|
304
304
|
> **Universal:** anything that speaks OpenAI-compatible HTTP gets transparent
|
|
305
|
-
> protection with *zero code*
|
|
305
|
+
> protection with *zero code* - set the Base URL to `shield.endpoint("openai")`
|
|
306
306
|
> and the key to your VK. That covers n8n, Flowise, Dify and raw HTTP, not just
|
|
307
307
|
> Python.
|
|
308
308
|
|
|
309
309
|
## Agentic tool enforcement
|
|
310
310
|
|
|
311
311
|
The part a base URL can't do: gate **local** tool execution. Each gated call
|
|
312
|
-
runs `decide()` first and the verdict maps to a Python outcome
|
|
312
|
+
runs `decide()` first and the verdict maps to a Python outcome - `ALLOW` runs
|
|
313
313
|
the body, `MASK` redacts PII kwargs, `REQUIRE_APPROVAL` blocks for a human, and
|
|
314
314
|
`DENY` raises `GuardrailDenied`.
|
|
315
315
|
|
|
316
|
-
### Zero extra code
|
|
316
|
+
### Zero extra code - enforcement is automatic and non-bypassable
|
|
317
317
|
|
|
318
318
|
The moment you construct `DeepintShield(...)`, the SDK installs guards for every
|
|
319
319
|
agent framework you've imported (LangGraph, CrewAI, LlamaIndex, AutoGen,
|
|
320
320
|
PydanticAI, the OpenAI Agents SDK, LiteLLM). After that, **compiling / building
|
|
321
|
-
an agent yields an already-governed object**
|
|
321
|
+
an agent yields an already-governed object** - you can't forget to gate it and
|
|
322
322
|
you can't bypass it by invoking the un-governed one (there isn't one).
|
|
323
323
|
|
|
324
324
|
```python
|
|
@@ -334,7 +334,7 @@ g = StateGraph(State)
|
|
|
334
334
|
g.add_node("read_step", crm_read)
|
|
335
335
|
g.add_node("admin_step", admin_grant)
|
|
336
336
|
...
|
|
337
|
-
app = g.compile() # auto-governed
|
|
337
|
+
app = g.compile() # auto-governed - every node now gated by the PDP
|
|
338
338
|
|
|
339
339
|
app.invoke({...}) # a DENY raises GuardrailDenied before the node runs
|
|
340
340
|
```
|
|
@@ -345,32 +345,32 @@ If you import a framework *after* building the client, call
|
|
|
345
345
|
> **Security follows the implementation, not the label.** Each node/tool is
|
|
346
346
|
> governed by its **function name** (`crm_read`), not the node label
|
|
347
347
|
> (`read_step`), and the decision is bound to a fingerprint of the function's
|
|
348
|
-
> **source**
|
|
348
|
+
> **source** - so editing the body is detected and policies target `crm_read`.
|
|
349
349
|
>
|
|
350
350
|
> **Trust boundary:** these client guards are cooperative defense-in-depth. A
|
|
351
351
|
> determined process can un-patch them or call a tool's raw function, so the
|
|
352
352
|
> gateway (MCP / LLM in the call path) remains the authoritative boundary.
|
|
353
353
|
|
|
354
|
-
### `govern()`
|
|
354
|
+
### `govern()` - register + threat-scan + instrument (explicit, idempotent)
|
|
355
355
|
|
|
356
356
|
`govern()` does everything the auto-guard does, explicitly: it **describes** the
|
|
357
357
|
agent's declared tool surface, **registers** that blueprint with the server
|
|
358
|
-
(which **threat-scans each tool's source** for RCE / shell-out / exfiltration
|
|
359
|
-
OWASP Agentic **T11 / T17**
|
|
358
|
+
(which **threat-scans each tool's source** for RCE / shell-out / exfiltration -
|
|
359
|
+
OWASP Agentic **T11 / T17** - server-side, ZDR), and **instruments** every call.
|
|
360
360
|
|
|
361
361
|
```python
|
|
362
|
-
app = shield.agentic.govern(app) # idempotent
|
|
362
|
+
app = shield.agentic.govern(app) # idempotent - safe alongside the auto-guard
|
|
363
363
|
```
|
|
364
364
|
|
|
365
365
|
A tool whose source scans malicious is flagged (Agentic → Findings) and, when
|
|
366
|
-
the workspace enables **Enforce code threat** (Rollout), denied
|
|
366
|
+
the workspace enables **Enforce code threat** (Rollout), denied - even if a
|
|
367
367
|
policy would otherwise allow it. A tool called but never declared shows up as
|
|
368
368
|
**ASI04 drift** under Agentic → Discovery.
|
|
369
369
|
|
|
370
|
-
### `guard()`
|
|
370
|
+
### `guard()` - LangChain callback / in-place instrument
|
|
371
371
|
|
|
372
372
|
`shield.agentic.guard()` (no argument) returns a native LangChain callback
|
|
373
|
-
handler; attaching it once gates *every* tool the agent calls
|
|
373
|
+
handler; attaching it once gates *every* tool the agent calls - the framework
|
|
374
374
|
supplies the tool name and the **gateway resolves the tier, policy, recovery
|
|
375
375
|
cost and identity server-side**.
|
|
376
376
|
|
|
@@ -382,7 +382,7 @@ agent_executor.invoke({"input": "…"}, config={"callbacks": [guard]})
|
|
|
382
382
|
`guard(target)` auto-detects and instruments a framework object in place:
|
|
383
383
|
|
|
384
384
|
```python
|
|
385
|
-
shield.agentic.guard(compiled_graph) # LangGraph
|
|
385
|
+
shield.agentic.guard(compiled_graph) # LangGraph - gate every tool node
|
|
386
386
|
shield.agentic.guard(crewai_tools) # CrewAI BaseTools
|
|
387
387
|
shield.agentic.guard(openai_agent) # OpenAI Agents FunctionTools
|
|
388
388
|
shield.agentic.guard(pydantic_agent) # PydanticAI agent
|
|
@@ -435,7 +435,7 @@ When the virtual key is bound to an identity provider, the SDK auto-discovers
|
|
|
435
435
|
the binding (`GET /api/agentic-security/vk-credential-info`), selects the right
|
|
436
436
|
credential (Entra Agent ID FIC / ZeroID RFC 8693 / generic OIDC), and attaches a
|
|
437
437
|
fresh `X-Agent-Token` on every decision. On Azure compute the Managed Identity
|
|
438
|
-
is detected automatically
|
|
438
|
+
is detected automatically - **no GUIDs, authority, or scopes in your code.**
|
|
439
439
|
|
|
440
440
|
```python
|
|
441
441
|
info = shield.agentic.credential_info # ops visibility into the binding
|
|
@@ -473,7 +473,7 @@ app = graph.compile()
|
|
|
473
473
|
## Multimodal guardrails (transparent)
|
|
474
474
|
|
|
475
475
|
Image generation, image edits, audio (TTS / transcription), video, embedding and
|
|
476
|
-
rerank requests are guarded **at the gateway**
|
|
476
|
+
rerank requests are guarded **at the gateway** - no SDK changes and no extra code.
|
|
477
477
|
Keep using the native provider SDKs through DeepIntShield; when the operator
|
|
478
478
|
enables `GUARDRAILS_MULTIMODAL`, the gateway evaluates the text these requests
|
|
479
479
|
already carry (image/TTS/video prompts, transcripts) and the binary artifacts
|
|
@@ -482,7 +482,7 @@ themselves, blocking or flagging per your policies.
|
|
|
482
482
|
```python
|
|
483
483
|
client = shield.openai()
|
|
484
484
|
|
|
485
|
-
# Guarded automatically
|
|
485
|
+
# Guarded automatically - the image prompt is evaluated before generation.
|
|
486
486
|
img = client.images.generate(model="gpt-image-1", prompt="a serene mountain lake")
|
|
487
487
|
|
|
488
488
|
# A blocked prompt surfaces as the provider SDK's normal HTTP error:
|
|
@@ -501,7 +501,7 @@ enforcing (`sync`) or observe-only (`shadow`).
|
|
|
501
501
|
|
|
502
502
|
## MCP
|
|
503
503
|
|
|
504
|
-
Generic MCP support
|
|
504
|
+
Generic MCP support - works with any server connected to your DeepintShield
|
|
505
505
|
gateway. No per-server SDK code; the same `Tool` / `MCPClient` API serves
|
|
506
506
|
DeepWiki, Context7, GitHub MCP, an internal one, and so on.
|
|
507
507
|
|
|
@@ -596,7 +596,7 @@ print(AgentExecutor(agent=agent, tools=mcp_tools).invoke(
|
|
|
596
596
|
)["output"])
|
|
597
597
|
```
|
|
598
598
|
|
|
599
|
-
LangGraph reuses the same `mcp_tools` list
|
|
599
|
+
LangGraph reuses the same `mcp_tools` list - drop them into a `ToolNode`.
|
|
600
600
|
|
|
601
601
|
---
|
|
602
602
|
|
|
@@ -605,16 +605,16 @@ LangGraph reuses the same `mcp_tools` list — drop them into a `ToolNode`.
|
|
|
605
605
|
The SDK automatically participates in the gateway's two cost-reduction layers
|
|
606
606
|
(both controlled by workspace switches under **Cost Optimization**):
|
|
607
607
|
|
|
608
|
-
- **Provider prompt caching**
|
|
608
|
+
- **Provider prompt caching** - every chat client returned by `shield.openai()`,
|
|
609
609
|
`shield.anthropic()`, etc. ships an `httpx` request hook that injects
|
|
610
610
|
Anthropic `cache_control` markers and an OpenAI `prompt_cache_key` so the
|
|
611
611
|
provider reuses KV state for the static prompt prefix. Cached tokens come
|
|
612
612
|
back at the provider's reduced rate (50% off OpenAI, 90% off Anthropic).
|
|
613
|
-
- **Gemini context caching**
|
|
613
|
+
- **Gemini context caching** - opt in with `shield.genai_cached()` (drop-in
|
|
614
614
|
for `shield.genai()`). The wrapper manages the `cachedContents` resource
|
|
615
615
|
lifecycle behind the scenes; the first call with a new static prefix runs
|
|
616
616
|
normally and the next call within the TTL window reuses the cache.
|
|
617
|
-
- **Semantic caching**
|
|
617
|
+
- **Semantic caching** - runs on the gateway; short-circuits requests whose
|
|
618
618
|
embeddings match a previous response within the configured similarity
|
|
619
619
|
threshold. The SDK doesn't need any code change to benefit; results flow
|
|
620
620
|
back through the normal API.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.3.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/credentials/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/__init__.py
RENAMED
|
File without changes
|
{deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/_common.py
RENAMED
|
File without changes
|
{deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/autogen.py
RENAMED
|
File without changes
|
{deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/crewai.py
RENAMED
|
File without changes
|
{deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/langchain.py
RENAMED
|
File without changes
|
{deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/langgraph.py
RENAMED
|
File without changes
|
{deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/litellm.py
RENAMED
|
File without changes
|
{deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/llamaindex.py
RENAMED
|
File without changes
|
{deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/openai_agents.py
RENAMED
|
File without changes
|
{deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/pydanticai.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|