Skip to main content

Saf3AI SDK for Python
Observability, security scanning, and data lineage for production AI agents

Python versions PyPI version License MIT


Overview

saf3ai-sdk is the official Python client for the Saf3AI platform. It combines:

  1. Observability — Saf3AI-native tracing with rich attributes (conversation IDs, models, usage, lineage).
  2. Security — Integration with the Saf3AI Scanner for prompt and optional response analysis, with policy callbacks.
  3. Governance — Automatic capture of data sources (HTTP, tools, DB access) onto traces for audit and compliance workflows.

Call init() once at process startup. The SDK detects your agent framework, configures the Saf3AI TraceProvider, connects to your Saf3AI platform account, and enables framework-aware instrumentation.


Table of contents

  • Why use this SDK
  • Platform capabilities
  • Architecture
  • Requirements
  • Installation
  • Quick start
  • Configuration
  • Supported frameworks
  • Observability conventions
  • Security scanning
  • Production checklist
  • API surface
  • Troubleshooting
  • Recent changes
  • Support & license

Why use this SDK

Need How the SDK helps
Single pane for agents One initialization path sends trace data to Saf3AI with consistent service and semantic attributes.
Safe defaults Scanner and platform auth can share SAF3AI_API_KEY unless explicitly overridden.
Framework drift Optional imports: install only ADK, LangChain, CrewAI, OpenAI Agents, AutoGen, or Bedrock; detection order is documented and predictable.
Operational clarity Conversation stitching and cross-framework capture improve troubleshooting in production.

Platform capabilities

Observability

  • Saf3AI TraceProvider owned by the SDK (set during init()).
  • Trace delivery to your Saf3AI platform workspace.
  • Framework tracers: saf3ai-adk, saf3ai-langchain, saf3ai-crewai, saf3ai-rest.
  • Optional console export for local development.

Security

  • Prompt scanning and optional response scanning via callbacks or direct helpers.
  • Policy hooks return allow/block; results can be attached to traces when enabled.

Data lineage

  • HTTP — Outbound request sources can be attached to active traces.
  • MCP — Tool and resource usage can be attached as lineage entries.
  • Databases — Database operations can be captured for governance and compliance contexts.

Architecture

flowchart TB
  classDef box fill:#f8fbff,stroke:#2b5876,stroke-width:1.5px,color:#0f172a;
  classDef platform fill:#eefbf3,stroke:#1f7a4a,stroke-width:1.5px,color:#0f172a;

  subgraph App["Application Layer"]
    A[Your Agent Experience]
  end

  subgraph SDK["Saf3AI SDK Layer"]
    I[Initialize SDK]
    T[Saf3AI TraceProvider]
    F[Framework Integrations]
    G[Security and Governance Controls]
  end

  subgraph Platform["Saf3AI Platform Layer"]
    P[Unified Saf3AI Platform]
  end

  A --> I
  I --> T
  I --> F
  I --> G
  T --> P
  F --> P
  G --> P

  class A,I,T,F,G box;
  class P platform;

Requirements

Item Detail
Python 3.9, 3.10, 3.11, or 3.12
Network Outbound HTTPS access to Saf3AI platform endpoints
Credentials Organization API key and Saf3AI account endpoint
Frameworks Optional: Google ADK, LangChain / LangFlow, CrewAI, OpenAI Agents, Microsoft AutoGen, or Amazon Bedrock — install only what you run

Installation

pip install saf3ai-sdk

This command installs the version currently published on PyPI. This checkout prepares 0.2.5; to verify it before publication, install it with pip install -e . and check python -m pip show saf3ai-sdk. Once published, deploy the tested version explicitly with pip install saf3ai-sdk==0.2.5.

Development dependencies (formatting, tests, types):

pip install saf3ai-sdk[dev]

Quick start

Initialize before you construct agents or LLM clients.

import os
from saf3ai_sdk import init, get_detected_framework

init(
    agent_id=os.environ["SAF3AI_AGENT_ID"],
    api_key=os.environ["SAF3AI_API_KEY"],
    safeai_collector_agent=os.environ["SAF3AI_COLLECTOR_AGENT"],
    service_name=os.getenv("SAF3AI_SERVICE_NAME"),
    scanner_endpoint=os.getenv("SAF3AI_SCANNER_ENDPOINT"),
    # Only needed when the policy's registered agent identifier differs from agent_id:
    scanner_agent_identifier=os.getenv("SAF3AI_SCANNER_AGENT_IDENTIFIER"),
)

print(get_detected_framework())  # e.g. "adk", "langchain", "crewai", "openai-agents", "autogen", "bedrock", "custom"

For richer configuration, pass an SDKConfig object into init() (see saf3ai_sdk.config.sdk_config).


Configuration

Required parameters or environment

Variable / parameter Purpose
agent_id Stable identifier for this agent instance in trace data
scanner_agent_identifier Registered agent identifier used by agent-scoped scanner rules; defaults to agent_id
api_key / SAF3AI_API_KEY Authenticates platform and scanner access
safeai_collector_agent Saf3AI endpoint base URL (required if not injected by your runtime wrapper)

Security: Never commit API keys. Use secret managers or CI-injected variables in production.

Frequently used optional variables

Variable Purpose
SAF3AI_SERVICE_NAME Human-readable service.name when different from agent_id
SAF3AI_SCANNER_ENDPOINT Scanner API base URL
SAF3AI_SCANNER_AGENT_IDENTIFIER Example application variable passed explicitly to scanner_agent_identifier; the SDK does not read it on its own
SAF3AI_SCAN_RESPONSES Scan model outputs (true / false)
SAF3AI_CAPTURE_RESPONSES Attach response text to traces when permitted by policy
SAF3AI_DEBUG_MODE Verbose SDK logging
SAF3AI_CONSOLE_OUTPUT Emit trace data to stdout (development)
SAF3AI_CLIENT_DATA_CAPTURE Client context enrichment where supported

Example: shell

export SAF3AI_API_KEY="your-key"
export SAF3AI_COLLECTOR_AGENT="https://collector.example.com"
export SAF3AI_SCANNER_ENDPOINT="https://scanner.example.com"
export SAF3AI_AGENT_ID="claims-agent-prod"

Supported frameworks

Detection order: ADK -> CrewAI -> LangChain -> OpenAI Agents -> AutoGen -> Bedrock -> custom.

Framework Auto-detected Built-in instrumentation after init()
Google ADK Yes Yes (saf3ai-adk)
LangChain / LangFlow Yes Yes (saf3ai-langchain)
CrewAI Yes Yes (saf3ai-crewai)
OpenAI Agents Yes Yes (saf3ai-openai-agents)
Microsoft AutoGen Yes Yes (saf3ai-autogen)
Amazon Bedrock Yes Yes (saf3ai-bedrock)
Custom / REST Fallback Yes (saf3ai-rest)

Install only the stack your service imports; the SDK selects the first matching framework.


Observability conventions

  • Traces include standardized Saf3AI metadata such as service.name, saf3ai.sdk.version, and environment.
  • Conversation stitching uses gen_ai.conversation.id and conversation_id helpers (get_conversation_id_unified, set_conversation_id_unified, reset_conversation).
  • Third-party spans may omit conversation attributes; the SDK aligns them with the unified conversation where possible.

Security scanning

Agent-scoped rules in 0.2.5

An agent-scoped rule matches only when the /scan request includes the exact registered identifier as metadata.agent_identifier. Automatic @traceable prompt and response scans now send it. The value comes from scanner_agent_identifier in init() (default: agent_id); @traceable(agent_identifier="...") overrides it for one decorated agent. Use the registered identifier, not a display name or function name. This is especially important when one process hosts multiple agents.

from saf3ai_sdk import init, traceable

init(
    agent_id="it-service-agent",
    api_key="...",  # Load from a secret manager or environment in production.
    safeai_collector_agent="https://your-collector.example",
    scanner_endpoint="https://your-scanner.example",
    scanner_agent_identifier="registered-policy-id",  # Must exactly match the policy identifier.
)

@traceable(name="it-service")
def answer(prompt: str) -> str:
    return call_your_model(prompt)

Replace the placeholder with the identifier actually registered for your agent, including its exact spelling. In the reported test this was it service agetn; a corrected-looking name would not match that rule. For a multi-agent process, put agent_identifier="..." on each @traceable decorator instead of relying on one process-wide default. Direct scan_prompt() and scan_response() calls still accept metadata={"agent_identifier": "..."}.

Detection and blocking are different. Automatic @traceable scanning records scan results; it does not, by itself, interpret every match as a block. To prevent a prompt reaching the model, register a policy callback that returns False on a block decision. The prompt callback now runs before the decorated function; the response callback runs before its result is returned. A framework adapter callback can scan again, so choose one scan/enforcement path per interaction where possible.

For a custom agent that needs blocking, use create_framework_security_callbacks(framework="custom", agent_identifier=..., on_scan_complete=...) before invoking the decorated function. on_scan_complete(text, scan_results, text_type) should implement your organization's policy and return True to allow or False to block. ADK, LangChain, CrewAI, and REST adapters also support explicit agent identifiers in their callback configuration. Test both a matching rule and a benign prompt before production.

def security_policy(text: str, scan_results: dict, text_type: str) -> bool:
    """text_type is 'prompt' or 'response' where applicable."""
    detections = scan_results.get("detection_results") or {}
    for _, result in detections.items():
        if isinstance(result, dict) and result.get("result") == "MATCH_FOUND":
            return False
    return True

Intentional policy blocks

Intentional policy blocks in custom agents should use the shared SDK exception:

from saf3ai_sdk import PolicyBlocked, traceable

@traceable(name="support-agent")
def answer(prompt: str) -> str:
    if policy_denies(prompt):  # Your application's policy decision.
        raise PolicyBlocked("Request denied by policy", phase="prompt", blocked_by="support-policy")
    return call_your_model(prompt)

Catch PolicyBlocked at the application boundary to return your blocked-request response. Replace any locally defined exception of that name with this import. Both synchronous and asynchronous @traceable functions propagate it while retaining block evidence, without recording a runtime failure. SDK-owned tracing contexts and call_llm_with_saf3ai() follow the same rule. Other exceptions still record errors; matching a threat in Monitor Only does not itself raise PolicyBlocked. When using a third-party tracing context around the SDK, its exception-recording policy remains under that library's control.

Production checklist

  • init() called once at cold start, before any tracer-backed client.
  • Secrets from environment or vault; never in source control.
  • Platform endpoint reachable from runtime network (VPC / egress rules).
  • Scanner endpoint and scan flags match organizational policy (prompt-only vs prompt+response).
  • Agent identity: capture one /scan request and verify metadata.agent_identifier exactly matches the registered rule identifier for each agent.
  • Enforcement: verify that a blocked prompt never enters the model/tool call and a blocked response is never returned to the caller. Automatic scanning alone is observational.
  • Failure policy: decide whether a scanner outage should allow or reject requests. Current callback error paths may fail open; test this against your security requirements.
  • agent_id / service_name stable per deployment unit for cost and ownership dashboards.
  • Log level appropriate (INFO or WARNING in production; DEBUG only when diagnosing).
  • Conversation IDs for multi-tenant apps: use explicit session-scoped IDs (reset_conversation() between unrelated chats).

API surface

Export Role
init(...) Configure trace provider, auth, framework and instrumentation wiring
get_detected_framework() Resolved framework string
get_tracer(name) Tracer from the SDK TraceProvider
traceable Trace decorator / wrapper for custom code paths
PolicyBlocked Intentional policy rejection; propagates without marking SDK-owned spans as runtime failures
call_llm_with_saf3ai(...) Model-call wrapper with prompt/response scan callbacks and enforcement evidence
set_scanner_config, set_global_security_callbacks Scanner wiring for traceable flows
scan_prompt, scan_response, scan_prompt_and_response Direct scanner HTTP APIs
set_custom_attributes, get_custom_attributes, clear_custom_attributes, reset_conversation Context and attribute helpers
create_security_callback ADK-oriented security callbacks (lazy import)
SDKConfig Typed configuration object for init()

Full parameter lists and behaviors live in docstrings in saf3ai_sdk/__init__.py and saf3ai_sdk.config.


Troubleshooting

Symptom What to verify
No traces SAF3AI_API_KEY, platform endpoint, firewall, and logs immediately after init()
Wrong framework Import order and installed packages (CrewAI is checked before LangChain)
Scanner not invoked scanner_endpoint, SAF3AI_API_KEY, and callbacks attached to the LLM or ADK agent
Rule matches only with manual metadata Install the fixed 0.2.5 release or this checkout, verify metadata.agent_identifier in the outgoing /scan payload, and check exact spelling against the registered policy identifier
Match appears but request was not blocked Configure and test an enforcement callback; automatic @traceable scanning records results but does not automatically turn every match into a block
Duplicate or fragmented conversations Ensure conversation ID helpers are used consistently per user session

Recent changes

0.2.5 release candidate (publish and deploy separately)

  • Agent identity is included in automatic prompt and response scans.
  • @traceable prompt-policy callbacks run before agent execution.
  • AutoGen and Bedrock automatic scan configuration paths are repaired.
  • Public PolicyBlocked preserves intentional block evidence without classifying the rejection as a runtime failure in sync/async decorators, SDK-owned contexts, and the model-call wrapper.
  • REST/custom callbacks propagate explicitly raised policy blocks.
  • AutoGen accepts generated callback signatures, records completed-scan markers, and enforces response blocks.
  • Automatic response scans respect SAF3AI_SCAN_RESPONSES; prompt text and attribute values are no longer printed at INFO level by @traceable.
  • Wheel and source archives use core metadata 2.4 for package-tool compatibility.

Local release verification

Run the local regression suite and build both distribution formats before publication:

python -m pytest -q tests
python -m build
python -m twine check dist/*

Tests, caches, and generated packages are intentionally Git-ignored and excluded from distribution archives. Keep the local test suite available in the release workspace; a fresh clone does not include those tests. Release notes remain version-controlled in this README and CHANGELOG.md. The sample-policy checks use mocked scanner/model calls; live framework and scanner validation must be performed against the deployment configuration.

The final local regression run passed 119 tests. Archive-content and installed-wheel smoke checks also verify that the packaged SDK exposes the expected API and reports version 0.2.5. Python 3.9 syntax was checked; the full regression run used Python 3.13 and does not replace runtime checks on your deployment's Python/framework versions.


Support & license

For security-sensitive reports, contact the maintainers directly rather than using public issues until a disclosure process is published.


Saf3AI and the Saf3AI logo are trademarks of their respective owners. This README describes the open-source saf3ai-sdk Python package.

Metadata

Release files for saf3ai-sdk 0.2.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for saf3ai-sdk 0.2.5
File Size Uploaded
saf3ai_sdk-0.2.5.tar.gz 181.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for saf3ai-sdk 0.2.5
File Interpreter ABI Platform
saf3ai_sdk-0.2.5-py3-none-any.whl Python 3 none any Details

Total release size: 390.1 kB

Release files / saf3ai_sdk-0.2.5.tar.gz

Download URL saf3ai_sdk-0.2.5.tar.gz
Size 181.8 kB
Tags Source
SHA-256 checksum
How to use checksums
cde8a4982404529c5f696b85d5aaba22875c8264fc06437a7658dd0b33a46d57
BLAKE2b-256 checksum
How to use checksums
2ba41846004ce39b237f5f21c80cf5e6ef3d31356114336a6f7f9d94177b77c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.13

Release files / saf3ai_sdk-0.2.5-py3-none-any.whl

Download URL saf3ai_sdk-0.2.5-py3-none-any.whl
Size 208.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8f9ba6cf5e33df7dc33547ac7105c4bf453614aba22596f93b06b16d667410be
BLAKE2b-256 checksum
How to use checksums
97d2ee1dcfabed094a2963c938d63548def5a54c511a09fd9d0c683779e7c55a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.13

Release history Release notifications | RSS feed

This release

0.2.5 This release

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page