Shared synchronous inter-service communication primitives for Apirify
Project description
apirify.package.communication
Shared synchronous inter-service communication package for Apirify.
apirify.package.communication provides the common HTTP communication primitives used by Apirify services when they need predictable synchronous service-to-service calls.
It standardizes envelopes, errors, correlation propagation, timeout behavior and FastAPI middleware so that internal HTTP communication stays explicit, observable and safe.
It does not own business logic.
It does not orchestrate Apirify flows.
It does not persist state.
It does not replace Kafka.
Canonical formula:
Kafka carries asynchronous events.
Communication package standardizes synchronous HTTP calls.
Role in Apirify
The package belongs to the Apirify infrastructure foundation layer.
It is used by services that need to call other services synchronously over HTTP while preserving Apirify's reliability and traceability guarantees.
Typical users:
apirify.service.gateway- internal FastAPI services
- Assistant control-plane services
- Dev domain services
- Semantic domain services
- Runtime foundation services
- OBRD services
- Hot runtime services
- service clients and integration adapters
The package is deliberately small and infrastructure-level.
It is not a domain service.
It is not a control plane.
It is not a gateway.
It is not an orchestrator.
It is not a shared business model library.
Purpose
apirify.package.communication exists to solve one narrow problem:
Make synchronous service-to-service communication predictable, observable and safe.
It standardizes:
- request envelopes
- response envelopes
- error envelopes
- typed error models
- correlation and tracing headers
- HTTP client behavior
- bounded timeouts
- retry policy boundaries
- request/response logging hooks
- FastAPI middleware for propagation
- common failure handling semantics
It keeps synchronous calls boring, explicit and inspectable.
Why This Package Exists
Apirify is a distributed platform with many specialized services and agents.
Some communication is asynchronous and event-driven. That belongs to Kafka.
Some communication is synchronous and request/response-based. Examples:
- Gateway calls an internal service.
- Actions calls a system-domain service to materialize a typed outcome.
- Runtime services request deterministic data from each other.
- Semantic services fetch explicit target metadata.
- OBRD services call narrowly scoped HTTP APIs during control-plane coordination.
Without a shared communication package, each service would invent its own:
- HTTP client configuration
- timeout behavior
- error format
- correlation propagation
- logging conventions
- response parsing
- exception mapping
That would create hidden differences across the platform.
This package prevents that.
Design Principles
Transport, not logic
This package defines how services communicate, not what they decide.
Domain decisions belong to domain services.
Explicit over magic
No hidden orchestration.
No invisible business behavior.
No implicit side effects.
HTTP calls must be visible and explainable.
Fail fast, fail typed
Timeouts and upstream failures must surface as explicit, typed errors.
The package should help avoid cascading failures by making failure boundaries clear.
Correlation by default
Every synchronous call should preserve traceability.
Correlation and causation metadata must be propagated through HTTP boundaries wherever possible.
Composable and boring
The package should be safe to use from any Apirify service.
It must stay small enough that teams can understand it quickly.
HTTP-first
HTTP is the current synchronous transport for Apirify service-to-service calls.
The package should not prevent future transport adapters, but it must not introduce transport abstraction for its own sake.
What This Package Is
apirify.package.communication is:
- a shared HTTP communication layer
- a foundation for service clients
- a home for request/response envelopes
- a home for error contracts
- a home for correlation header utilities
- a home for FastAPI propagation middleware
- a standard place for bounded HTTP client behavior
- an infrastructure package used by multiple Apirify services
What This Package Is Not
apirify.package.communication is not:
- a common utils dump
- a service registry
- a business abstraction layer
- a domain model package
- an orchestration package
- an Assistant package
- a Gateway implementation
- an Actions implementation
- a Kafka replacement
- a persistence package
- a place for product-specific logic
The package must not become a dumping ground.
If a feature is not about synchronous communication contracts or HTTP propagation, it probably does not belong here.
Gateway Relationship
apirify.service.gateway is the frontend-facing HTTP boundary of Apirify.
Gateway is responsible for:
- routing
- auth/session propagation
- request normalization
- frontend-facing API boundary
- controlled access to internal services
This package may be used by Gateway and by services behind Gateway.
But the distinction is important:
Gateway routes external-facing requests.
Communication package standardizes internal synchronous calls.
Gateway decides routing boundaries.
The communication package does not.
Gateway owns frontend-facing HTTP behavior.
The communication package owns reusable communication primitives.
Kafka Relationship
Kafka is the canonical asynchronous event backbone of Apirify.
This package does not replace Kafka.
Use Kafka for:
- events
- job lifecycle messages
- async workflows
- durable state transitions
- fan-out notifications
- long-running execution coordination
- service/agent event contracts
Use this package for:
- synchronous HTTP calls
- request/response service APIs
- direct service queries
- bounded control-plane calls
- middleware-level header propagation
- typed HTTP error handling
Canonical rule:
If the caller needs an immediate bounded response, HTTP may be appropriate.
If the system needs durable asynchronous workflow, use Kafka.
Package Structure
Current package import root:
apirify_communication/
Expected high-level structure:
apirify_communication/
contracts/
envelopes.py
errors.py
http/
client.py
middleware.py
The exact internal module structure may evolve, but the public API should remain small and explicit.
Installation
From PyPI
Recommended for Apirify services once the package is published:
pip install apirify-package-communication==0.2.8
Production builds must use pinned versions.
Do not use floating versions in Dockerfiles or CI pipelines.
Local development
From a neighboring checkout:
pip install -e ../apirify.package.communication
Legacy Git installation
Older services may still install the package directly from Git:
pip install "apirify-package-communication @ git+https://github.com/vyadzmak/apirify.package.communication.git@v0.2.8"
This should be replaced with the pinned PyPI dependency after publication:
apirify-package-communication==0.2.8
Python Import
Package distribution name:
apirify-package-communication
Python import root:
import apirify_communication
Version check:
import apirify_communication
print(apirify_communication.__version__)
Example imports:
from apirify_communication.http.client import BaseHttpClient
from apirify_communication.contracts.envelopes import RequestEnvelope
Actual imports should follow the current public API exposed by the package.
Correlation and Tracing
All synchronous calls are expected to propagate correlation metadata.
Default correlation header:
X-Correlation-Id
The same correlation id should:
- enter through Gateway or another trusted request boundary
- propagate through internal synchronous calls
- appear in service logs
- connect request logs with events and evidence where applicable
- help diagnose failures across services
The package should make correlation propagation easy and consistent.
It must not hide missing correlation metadata silently when strict mode is enabled.
Error Handling
Synchronous communication must fail explicitly.
The package should support typed handling for:
- upstream timeout
- upstream connection failure
- upstream 4xx response
- upstream 5xx response
- invalid response envelope
- invalid error envelope
- missing required correlation metadata
- request serialization failure
- response parsing failure
Errors should carry enough information for diagnostics without leaking secrets.
Expected diagnostic fields may include:
- service name
- target URL or logical target, when safe
- status code
- error code
- correlation id
- request id, when available
- retryability hint
- safe message
No fake success.
No swallowed upstream failures.
No secret leakage.
Timeout Policy
HTTP calls must be bounded.
The package should encourage explicit timeout configuration instead of relying on library defaults.
Timeouts should be chosen by caller context:
- short timeouts for user-facing paths
- stricter limits for Gateway-facing flows
- bounded internal timeouts for control-plane calls
- no infinite waits
A service that needs durable long-running work should not hold synchronous HTTP calls open indefinitely.
Use Kafka/job lifecycle for long-running execution.
Retry Policy
Retries must be explicit and conservative.
The package must not introduce hidden retry behavior that can:
- duplicate side effects
- hide upstream instability
- amplify load
- break idempotency assumptions
- make failures harder to understand
If retry support is used, it must be bounded and safe for the operation type.
Default philosophy:
No hidden retries.
Explicit retry policy only.
Middleware
The package may provide FastAPI middleware for:
- reading incoming correlation headers
- creating correlation metadata when allowed by boundary policy
- storing request-local metadata
- propagating metadata to outgoing clients
- adding response headers
- standardizing error envelope behavior
Middleware must stay infrastructure-level.
It must not contain domain-specific decisions.
Service Client Pattern
A service-specific client should use this package as its communication foundation.
Example conceptual pattern:
class SourcesClient(BaseHttpClient):
async def get_snapshot(self, snapshot_id: str):
return await self.get(
path=f"/v1/source-snapshots/{snapshot_id}",
expected_status=200,
)
The package provides the HTTP behavior.
The service-specific client provides the domain-specific method names and paths.
Keep the boundary clear:
Communication package owns transport behavior.
Service client owns service-specific API shape.
Domain service owns business meaning.
Usage Scope
Use this package in services that need synchronous HTTP communication with other Apirify services.
Good candidates:
- Gateway-to-service calls
- Actions-to-system-service calls
- Runtime foundation service calls
- Semantic domain service calls
- Assistant control-plane service calls
- OBRD control-plane service calls
- Hot runtime control-plane calls
Avoid using synchronous HTTP calls for work that should be asynchronous, durable or event-driven.
Non-responsibilities
apirify.package.communication must not:
- decide routes
- classify user intent
- build execution plans
- call LLMs
- apply source patches
- create projects
- start OBRD runs by itself
- run Hot sessions
- own service state
- own database transactions
- define Apirify product domain models
- replace domain-specific clients
- replace Kafka
- hide partial failures
- retry forever
The package carries calls.
Services own meaning.
Security Rules
The package must treat all inbound and outbound data as untrusted.
Rules:
- never log secrets
- never log raw authorization headers
- never log sensitive payloads by default
- redact known sensitive headers
- preserve correlation metadata safely
- avoid leaking internal stack traces across service boundaries
- expose typed safe errors
- keep timeout behavior bounded
- keep TLS and verification settings explicit when applicable
Sensitive values belong to runtime.secrets or service configuration, not to communication helpers.
Versioning Policy
This package follows Semantic Versioning.
MAJOR — breaking changes in envelopes, errors or client behavior
MINOR — backward-compatible additions
PATCH — fixes only
Production services should pin exact versions:
apirify-package-communication==0.2.8
Do not use floating versions in production pipelines.
Reproducibility matters more than convenience.
Release Checklist
Before publishing a new version:
- Update
pyproject.tomlversion. - Update
src/apirify_communication/__init__.pyversion. - Run tests.
- Build the package.
- Check distributions.
- Install the wheel in a clean virtual environment.
- Verify imports.
- Publish to TestPyPI first when needed.
- Publish to PyPI.
- Update Apirify service requirements with an exact pinned version.
Example commands:
rm -rf dist/ build/ src/*.egg-info
python -m pip install --upgrade build twine
python -m build
python -m twine check dist/*
Local wheel verification:
python -m venv /tmp/apirify-communication-test
source /tmp/apirify-communication-test/bin/activate
pip install dist/*.whl
python -c "import apirify_communication; print(apirify_communication.__version__)"
deactivate
Apirify Reliability Principles
This package supports the core Apirify engineering principles:
- We do not crash — bounded calls, explicit errors, safe failure handling.
- We do not slow down — no hidden blocking behavior, no unbounded retries.
- We do not make mistakes — explicit contracts, typed envelopes and traceable calls.
And the broader engineering motto:
No magic. Just engineering.
If a feature makes communication less explicit, less observable or less bounded, it does not belong here.
Status
Stable internal Apirify package.
The public API should remain intentionally small and evolve carefully.
Breaking changes must be rare, explicit and coordinated across services.
License
Internal Apirify package.
Not intended for public reuse outside the Apirify ecosystem unless explicitly published and documented otherwise.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file apirify_package_communication-0.2.8.tar.gz.
File metadata
- Download URL: apirify_package_communication-0.2.8.tar.gz
- Upload date:
- Size: 21.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f48174b4fb3122a106585b1599042a71dec49605564a565629cf9d5c6aff02a7
|
|
| MD5 |
f165407996a5383490ecc2602116bf11
|
|
| BLAKE2b-256 |
f2546f6fcd47c679d9e8a8879d6e481828ed6deb3e0f1eed6dd4e9189526300d
|
File details
Details for the file apirify_package_communication-0.2.8-py3-none-any.whl.
File metadata
- Download URL: apirify_package_communication-0.2.8-py3-none-any.whl
- Upload date:
- Size: 21.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4cd616ecd8ef1d24f651e663163c0d7909b65550dd1f6cb6217a69089e1f7e73
|
|
| MD5 |
b2f4ca1233211275f4e0c8b9719baa07
|
|
| BLAKE2b-256 |
a8c2afe3fa4848b516872eb6fbda55769fdf6df7939cbb17f2c4d4eb03969e40
|