Skip to content

feat(sdk): add external sink#175

Merged
namrataghadi-galileo merged 17 commits intomainfrom
feature/62793-add-external-sink
Apr 21, 2026
Merged

feat(sdk): add external sink#175
namrataghadi-galileo merged 17 commits intomainfrom
feature/62793-add-external-sink

Conversation

@namrataghadi-galileo
Copy link
Copy Markdown
Contributor

Summary

Added a vendor-neutral external control-event sink registration API in the Python SDK so integrations can receive finalized ControlExecutionEvent payloads without adding vendor-specific logic to OSS.

Updated observability delivery so observability_enabled is the master gate, and when enabled the SDK uses registered sinks if present, otherwise the existing default OSS batcher sink.

Added docs and test coverage for sink registration, override behavior, fallback to default delivery, and local/server/merged event delivery parity.

Scope

User-facing/API changes:

  • Added register_control_event_sink(...), unregister_control_event_sink(...), and get_registered_control_event_sinks(...) to the Python SDK public API
  • Documented how external integrations can register a sink

Internal changes:

  • Added active sink resolution in the SDK observability layer
  • Enforced observability_enabled before any sink delivery occurs
  • Preserved existing event construction flow for local, server, merged, and partial/error cases
  • Added mock-sink tests covering override semantics and delivery behavior

Out of scope:

  • Config-driven sink selection for SDK/server
  • OTEL sink implementation and configuration
  • Server-side sink resolution changes

Risk and Rollout

Risk level: medium

Rollback plan: Revert the SDK observability sink-resolution changes and public sink registration API additions in the Python SDK. Since default OSS delivery remains the fallback when no external sink is registered, rollback is isolated to the SDK observability layer.

Testing

  • Added or updated automated tests
  • Ran make check — focused validation was run instead. Full workspace checks were unnecessary for this scoped SDK change. There is also a pre-existing unrelated SDK typecheck issue around google.adk untyped imports.
  • Manually verified behavior

Checklist

  • Linked issue/spec (if applicable)
  • Updated docs/examples for user-facing changes
  • Included any required follow-up tasks

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 16, 2026

Codecov Report

❌ Patch coverage is 94.59459% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
sdks/python/src/agent_control/observability.py 94.59% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

@lan17 lan17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the direction here, but I don't think this base PR is ready to merge yet. The main thing I'd fix first is the enabled= override becoming sticky process state. I also think we need an explicit lifecycle/ownership story for external sinks before we merge the base abstraction.

Comment thread sdks/python/src/agent_control/observability.py Outdated
Comment thread sdks/python/src/agent_control/observability.py
@namrataghadi-galileo
Copy link
Copy Markdown
Contributor Author

@lan17 Thanks, I agree those were the two biggest issues in the base abstraction.

I fixed the sticky enabled= behavior first. init_observability(enabled=...) no longer writes back into the process-global SDK settings, so it now behaves as a per-call override for that initialization path instead of poisoning later init/re-init flows for the rest of the process.

I also made the external-sink ownership model explicit. Caller-registered sinks are now documented as caller-owned: the SDK does not flush, close, or unregister them during shutdown, and shutdown_observability() only drains SDK-owned resources like the built-in batcher. I added regression coverage for both behaviors so the base API has a clear lifecycle boundary before we build on it further.

Copy link
Copy Markdown
Contributor

@lan17 lan17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. The main issues from the earlier round were addressed, and the overall shape here makes sense. I left a couple of follow-up comments around fanout semantics and sink registration bookkeeping, but I don't think either one should hold this up.

Comment thread sdks/python/src/agent_control/observability.py
Comment thread sdks/python/src/agent_control/observability.py
@namrataghadi-galileo namrataghadi-galileo merged commit 45f3645 into main Apr 21, 2026
6 checks passed
@namrataghadi-galileo namrataghadi-galileo deleted the feature/62793-add-external-sink branch April 21, 2026 22:29
galileo-automation pushed a commit that referenced this pull request Apr 22, 2026
## [2.4.0](ts-sdk-v2.3.0...ts-sdk-v2.4.0) (2026-04-22)

### Features

* **evaluators:** add built-in budget evaluator for per-agent cost tracking ([#144](#144)) ([d4ce113](d4ce113)), closes [#130](#130)
* **sdk:** add external sink ([#175](#175)) ([45f3645](45f3645))
* **server:** Align condition and template depth limits ([#166](#166)) ([03f402e](03f402e))
* **server:** Phase 0: add control version history and soft-delete unusable legacy controls ([#172](#172)) ([e5b2b33](e5b2b33))

### Bug Fixes

* **examples:** fix crewai examples ([#179](#179)) ([9004ea3](9004ea3))
@galileo-automation
Copy link
Copy Markdown
Collaborator

🎉 This PR is included in version 2.4.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants