feat(architecture): add opt-in agent and integration adapters#6
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Introduces two opt-in integration surfaces and the supporting outbox infrastructure to extend the Cosmic Python template without making MCP or Kafka required dependencies.
Changes:
- Add MCP primary adapter (tool + resource) and Kafka secondary adapter for an external
IntegrationMessageBusport, both behind optional extras. - Add a transactional outbox (
outbox_eventstable, migration, staging inSqlAlchemyUnitOfWork, broker-neutral relay use case) with a versionedUserRegisteredV1integration event. - Document the design in ADR 0015 (MCP) and ADR 0016 (outbox), update AGENTS guidance, README, and Make/Compose targets.
Reviewed changes
Copilot reviewed 39 out of 40 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
uv.lock |
Locks new transitive deps for the mcp and kafka extras. |
pyproject.toml |
Declares mcp and kafka optional-dependency groups and updates coverage omits. |
Makefile |
Adds mcp, kafka-up/relay/consume/ui-* targets; runs lint/coverage with both extras. |
docker-compose.yaml |
Adds local KRaft Kafka and optional Kafbat UI under observability profile. |
README.md |
Documents MCP/Kafka addons and KAFKA_* env vars. |
AGENTS.md |
Adds guidance for MCP adapter and outbox-based external publication. |
docs/adr/0015-*.md |
New ADR: MCP is an opt-in primary adapter. |
docs/adr/0016-*.md |
New ADR: external buses go through a transactional outbox. |
docs/adr/README.md, docs/cosmic-python-coverage.md |
Index and coverage matrix updates for the new ADRs. |
migrations/env.py, migrations/versions/20260531_0002_*.py |
Registers OutboxRecord for Alembic and creates outbox_events. |
src/template/adapters/models/outbox.py |
New SQLAlchemy mapping for outbox rows. |
src/template/adapters/outbox.py |
Stages integration events and provides relay UoW/repository. |
src/template/adapters/unit_of_work.py |
Stages integration events during commit with id-based deduplication. |
src/template/integration_events/{__init__,user}.py |
Versioned camel-case UserRegisteredV1 envelope. |
src/template/service_layer/integration_messagebus.py |
Broker-neutral publish port. |
src/template/service_layer/outbox.py |
Relay use case, abstract outbox UoW, OutboxMessage. |
src/template/settings/kafka_settings.py |
KAFKA_* settings for the relay/adapter. |
src/template/addons/__init__.py, addons/mcp/*, addons/kafka/* |
MCP application/server and Kafka adapter/worker behind optional imports. |
tests/unit/..., tests/integration/... |
New unit/integration tests for outbox, integration events, Kafka adapter, MCP application/server, and updates to persistence/migration tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
IntegrationMessageBusservice-layer portWhy
Agent clients benefit from MCP tools and resources, but MCP should not become a default dependency or automatic HTTP route mirror. External event publication also needs a Cosmic Python boundary: application orchestration depends on
IntegrationMessageBus, while Kafka remains replaceable by RabbitMQ, SQS, or another adapter.The transactional outbox avoids a dual-write gap between relational persistence and external broker publication. The relay provides at-least-once delivery, with
eventIddocumented as the consumer deduplication key.Showcase
User registration now demonstrates the full flow:
UserRegisteredUserRegisteredV1outbox row atomicallyusers.events, keyed byuserIdThe MCP addon demonstrates
onboard_useras a tool andusers://{user_id}as a resource backed by the existing command bus and CQRS reader.Validation
uv run pre-commit run --all-filesmake lintmake cover(56 passed,100%coverage)make adr-checkuv lock --checkgit diff --checkdocker compose config --quietdocker compose --profile observability config --quietIntegrationMessageBus/actuator/healthprobe52 passed, 2 skipped