Skip to main content

watchlight-core

Shared HTTP client and governance primitives used by every Watchlight AI framework plugin (watchlight-adk, watchlight-langgraph, watchlight-bedrock, …).

Why this exists

Until #312, the same APDP HTTP client lived as three near-identical copies under each framework plugin. As the contract stabilised across ADK / LangGraph / Bedrock, three copies became the right trigger for extraction. This package is the single source of truth for:

  • The HTTP wire format with WL-APDP (ApdpClient)
  • Plan-validation / preflight result wrappers (PlanResult, PreflightResult)
  • The plan-normalisation contract (normalize_plan)
  • The framework-agnostic GovernanceState shape consumed by the Beacon Dashboard / Streamlit governance card
  • The base run-handle lifecycle (BaseRunHandle)
  • Shared error types and the governance_mode env reader
  • Plugin telemetry contract (GovernanceTelemetry)

What's intentionally NOT here

Framework-specific behaviour stays in the plugin packages:

  • ADK lifecycle callbacks + PlanReActPlanner parser + BaseToolsetwatchlight-adk
  • LangGraph plan-and-execute primitives — watchlight-langgraph
  • AWS Bedrock event parsing + Lambda action-group decorator + bedrock_session_attributes() helper — watchlight-bedrock

Install

# Minimal — APDP client + governance primitives only
pip install watchlight-core

# With OpenTelemetry export support (adds ~50MB of OTel SDK deps)
pip install 'watchlight-core[otlp]'

# Or in this monorepo:
pip install -e plugins/watchlight-core
pip install -e 'plugins/watchlight-core[otlp]'

Plugins depend on it explicitly via their pyproject.toml; the core package depends only on httpx and (on Python 3.10) typing-extensions. The [otlp] extra pulls in opentelemetry-api, opentelemetry-sdk, and opentelemetry-exporter-otlp-proto-http — optional so cold-start- sensitive environments (Lambda, Cloudflare Workers) don't pay the install weight when they're not exporting to OTel.

Public API

from watchlight_core import (
    # HTTP client
    ApdpClient,

    # Errors
    WatchlightError,
    AgentNotRegistered,
    GovernanceUnavailable,

    # Result wrappers
    PlanResult,
    PreflightResult,

    # Plan / state
    normalize_plan,
    GovernanceState,
    GovernanceTelemetry,
    state_from_attrs,

    # Lifecycle
    BaseRunHandle,
    GovernedPlugin,

    # Custom-agent SDK (EN.6)
    watchlight,

    # OpenTelemetry export (EN.6) — requires [otlp] extra at construction
    OtlpConfig,
    OtlpProfile,
    WatchlightOtlpExporter,

    # Env
    governance_mode,
)

Custom-agent SDK (@watchlight)

For agents NOT built on a framework with a Watchlight plugin (LangGraph, ADK, Bedrock), the @watchlight decorator emits the canonical lineage events for any Python function:

from watchlight_core import ApdpClient, watchlight

client = ApdpClient(base_url="http://localhost:8081")

@watchlight(agent_id="custom-research", apdp_client=client)
async def run_research(query: str) -> str:
    # Your agent logic — emits execution_started / completed / failed
    return result

OpenTelemetry export

Opt-in customer observability — sends a deliberate subset of the lineage stream to your OTel collector. Default is profile=off; the exporter is a no-op until you turn it on.

from watchlight_core import OtlpConfig, WatchlightOtlpExporter

# Profile ladder: off ⊂ metrics ⊂ standard ⊂ governance
otlp = WatchlightOtlpExporter(OtlpConfig.from_env())
# WL_OTLP_PROFILE=standard
# WL_OTLP_ENDPOINT=http://otel-collector:4318

Tool arguments, LLM prompts, ABR raw scores, drift baselines, and security-internal anomalies never leave Watchlight. The exported subset is documented in dev-docs/architecture/otlp-export.md.

The package exposes a py.typed marker so type checkers (mypy, pyright) pick up the inline annotations directly.

Contract stability

Anything in watchlight_core/__init__.py's __all__ is a stable public API under SemVer minor-version compatibility. Anything else is internal and may move between minor versions.

When changing the wire format with WL-APDP (e.g. adding a route or field), update ApdpClient here — the plugins inherit it for free.

Building a new plugin

Implement the framework integration surface (lifecycle hooks, native plan format, etc.) in your plugin package and use this package for everything else:

  1. Inherit GovernanceTelemetry to satisfy the last_* contract.
  2. For frameworks with explicit primitives (LangGraph, Bedrock): subclass BaseRunHandle and add framework-specific helpers; expose start_run(slug) returning your subclass.
  3. For frameworks with lifecycle callbacks (ADK): use ApdpClient directly and populate the last_* attributes from your callbacks.
  4. Provide a one-line state_from_<framework>_plugin state helper using state_from_attrs(plugin, framework="<name>").

The GovernanceState shape parity test in your plugin's test suite guarantees the dashboard renders consistently across frameworks.

Cross-references

  • Multi-framework contract: dev-docs/architecture/proxy-plugin-interop.md §6
  • Threat model: dev-docs/security/HARDENING.md (entries #301, #312, plus this PR's entry)

Open-source by design — the plugin is glue

This package (and the framework plugins built on it) ships as readable, Apache-2.0 source. That's safe because all authorization decisions, scope strict-subset attenuation, lineage/audit signing, and drift/anomaly scoring are server-side — in the compiled Rust core (wl-apdp) and the governed platform. The plugin registers hooks, shapes a request, round-trips it to the PDP, and projects the answer.

There is no differentiating IP to strip for a community build: the difference between Developer Edition and Enterprise is the backend the plugin talks to (the in-process DE engine vs. the full governed plane), never the plugin code. And because any decision made client-side is bypassable, keeping enforcement server-side is a security rule, not just an IP one.

This boundary is documented in plugins/CONTRIBUTING.md and enforced in CI by the plugin IP-boundary gate (scripts/ci/check_plugin_ip_boundary.py).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

watchlight_agent_sdk-0.5.0.tar.gz (322.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

watchlight_agent_sdk-0.5.0-py3-none-any.whl (202.5 kB view details)

Uploaded Python 3

File details

Details for the file watchlight_agent_sdk-0.5.0.tar.gz.

File metadata

  • Download URL: watchlight_agent_sdk-0.5.0.tar.gz
  • Upload date:
  • Size: 322.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for watchlight_agent_sdk-0.5.0.tar.gz
Algorithm Hash digest
SHA256 65a919ccef9c724dc48e9f69233b220f0d6c12aad8c43db863ee3f8881ed89f5
MD5 97cc8d96543f64ab1cfa0a6f7ec73391
BLAKE2b-256 48eb9bea95b8a596f387a8b5ae0fa05b6924d0944a81444e0aac9a63999223f0

See more details on using hashes here.

Provenance

The following attestation bundles were made for watchlight_agent_sdk-0.5.0.tar.gz:

Publisher: publish-python-sdk-plugins.yml on watchlight-ai-beacon/watchlight-beacon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file watchlight_agent_sdk-0.5.0-py3-none-any.whl.

File metadata

File hashes

Hashes for watchlight_agent_sdk-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e2981ce91cc676a9dc52c3e70be26eff55776654e4c059fc1ed544ba206c747b
MD5 abc628c084c1b74fe22006bad42d9b13
BLAKE2b-256 238c3a800725c99a80f4dcd64bc0dcd22f2d9c9d187d4e03a3b210de58ed8fd7

See more details on using hashes here.

Provenance

The following attestation bundles were made for watchlight_agent_sdk-0.5.0-py3-none-any.whl:

Publisher: publish-python-sdk-plugins.yml on watchlight-ai-beacon/watchlight-beacon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page