10 KiB
Sensor Agent Injection Plan
Overview
The sensor service is positioned similarly to the worker service: it is a long-running process that dispatches sensor commands into underlying runtimes rather than containing runtime-specific logic in the service binary itself. The worker side now supports injected, statically-linked agent binaries that run inside arbitrary container images. This plan extends the same model to sensors.
Goal:
- Replace the pre-built
attune-sensorcontainer image in default deployments with an injected sensor agent binary running inside stock runtime images - Reuse the existing runtime auto-detection and capability reporting model
- Preserve current sensor behavior, including runtime-based execution, registration, heartbeat, and graceful shutdown
Non-goals:
- Converging worker and sensor into a single binary
- Redesigning sensor scheduling or runtime execution semantics
- Removing existing
ATTUNE_SENSOR_RUNTIMESoverrides
Current State
Relevant implementation points:
- Sensor startup entrypoint: crates/sensor/src/main.rs
- Sensor service orchestration: crates/sensor/src/service.rs
- Sensor capability registration: crates/sensor/src/sensor_worker_registration.rs
- Shared runtime detection: crates/common/src/runtime_detection.rs
- Current sensor container build: docker/Dockerfile.sensor.optimized
- Existing worker-agent design reference: docs/plans/universal-worker-agent.md
Observations:
- Sensors already use the same three-tier capability detection model as workers:
ATTUNE_SENSOR_RUNTIMES- config file capabilities
- database-driven verification
- The main missing piece is packaging and entrypoint behavior, not capability modeling
- The current sensor Compose service still depends on a pre-built Rust binary baked into the container image
- The sensor manager relies on shared runtime environment assumptions such as interpreter paths and
runtime_envscompatibility
Proposed Architecture
Introduce a dedicated injected binary, attune-sensor-agent, analogous to the existing attune-agent for workers.
Responsibilities of attune-sensor-agent:
- Probe the container for available interpreters before the Tokio runtime starts
- Respect
ATTUNE_SENSOR_RUNTIMESas a hard override - Populate
ATTUNE_SENSOR_RUNTIMESautomatically when unset - Support
--detect-onlyfor diagnostics - Load config and start
SensorService
This should remain a separate binary from attune-agent.
Reasoning:
attune-agentis worker-specific today and bootsWorkerService- Sensor startup and runtime semantics are related but not identical
- A shared bootstrap library is useful; a single polymorphic agent binary is not necessary
Implementation Phases
Phase 1: Add Sensor Agent Binary
Add a new binary target under the sensor crate, likely:
name = "attune-sensor-agent"path = "src/agent_main.rs"
The new binary should mirror the startup shape of crates/worker/src/agent_main.rs, but target sensors instead of workers.
Expected behavior:
- Install the crypto provider
- Initialize tracing
- Parse CLI flags:
--config--name--detect-only
- Detect runtimes synchronously before Tokio starts
- Set
ATTUNE_SENSOR_RUNTIMESwhen auto-detection is used - Load config
- Apply sensor name override if provided
- Start
SensorService - Handle SIGINT/SIGTERM and call
stop()
Phase 2: Reuse and Extract Shared Bootstrap Logic
Avoid duplicating the worker-agent detection/bootstrap code blindly.
Extract shared pieces into a reusable location, likely one of:
attune-common- a small shared helper module in
crates/common - a narrow internal library module used by both worker and sensor crates
Candidate shared logic:
- pre-Tokio runtime detection flow
- override handling
--detect-onlyreporting- environment mutation rules
Keep service-specific startup separate:
- worker agent starts
WorkerService - sensor agent starts
SensorService
Phase 3: Docker Build Support for Injected Sensor Agent
Extend the current agent binary build pipeline so the statically-linked sensor agent can be published into the same shared volume model used for workers.
Options:
- Extend docker/Dockerfile.agent to build and copy both
attune-agentandattune-sensor-agent - Or add a sibling Dockerfile if the combined build becomes unclear
Preferred outcome:
init-agentpopulates/opt/attune/agent/attune-agentinit-agentalso populates/opt/attune/agent/attune-sensor-agent
Constraints:
- Keep the binaries statically linked
- Preserve the existing API binary-serving flow from the
agent_binvolume - Do not break current worker agent consumers
Phase 4: Compose Integration for Sensor Agent Injection
Replace the current sensor service in docker-compose.yaml with an agent-injected service.
Target shape:
- stock runtime image instead of
docker/Dockerfile.sensor.optimized entrypoint: ["/opt/attune/agent/attune-sensor-agent"]depends_on.init-agent- same config, packs, runtime env, and log/artifact mounts as required
Required environment variables must be preserved, especially:
ATTUNE_CONFIGATTUNE__DATABASE__URLATTUNE__MESSAGE_QUEUE__URLATTUNE_API_URLATTUNE_MQ_URLATTUNE_PACKS_BASE_DIR
Recommended default image strategy:
- Use a stock image that includes the default runtimes the sensor service should expose
- Be conservative about path compatibility with worker-created runtime environments
Phase 5: Native Capability Handling
Sensors have the same edge case as workers: native is a capability but not a discoverable interpreter.
Implication:
- Pure auto-detection can discover Python, Node, Shell, Ruby, etc.
- It cannot infer
nativesafely from interpreter probing alone
Plan:
- Keep explicit
ATTUNE_SENSOR_RUNTIMES=...,nativefor any default full-capability sensor image - Revisit later only if native becomes a first-class explicit capability outside interpreter discovery
Phase 6: Runtime Environment Compatibility
The current sensor image documents an important invariant: sensors and workers share runtime_envs, so interpreter paths must remain compatible.
This must remain true after the migration.
Validation criteria:
- Python virtual environments created by workers remain usable by sensors
- Node runtime assumptions remain compatible across images
- No new symlink breakage due to mismatched interpreter installation paths
If necessary, prefer stock images whose paths align with the worker fleet, or explicitly document where sensor and worker images are allowed to diverge.
Phase 7: Documentation and Examples
After implementation:
- Update docs/plans/universal-worker-agent.md with a sensor extension or cross-reference
- Update docker-compose.yaml
- Update docker-compose.agent.yaml if it should also include sensor examples
- Add or update quick references for sensor agent injection
The message should be clear:
- Workers and sensors both support injected static agent binaries
- Runtime images are now decoupled from Rust service image builds
Recommended Implementation Order
- Add
attune-sensor-agentbinary and make it bootSensorService - Extract shared bootstrap logic from the worker-agent path
- Extend the agent Docker build/init path to include the sensor agent binary
- Replace the Compose
sensorservice with an injected sensor-agent container - Validate runtime detection and one end-to-end Python, Node, and native sensor path
- Update docs and examples
Risks
Worker-Agent Coupling
Risk:
- Trying to reuse
attune-agentdirectly for sensors will conflate worker and sensor startup semantics
Mitigation:
- Keep separate binaries with shared helper code only where it is truly generic
Native Capability Loss
Risk:
- Auto-detection does not capture
native
Mitigation:
- Preserve explicit
ATTUNE_SENSOR_RUNTIMESwhere native support is required
Runtime Path Mismatch
Risk:
- Switching to a stock image may reintroduce broken venv or interpreter path issues
Mitigation:
- Validate image interpreter paths against shared
runtime_envs - Prefer images that align with worker path conventions when possible
Missing Environment Contract
Risk:
- The sensor manager currently depends on env vars such as
ATTUNE_API_URL,ATTUNE_MQ_URL, andATTUNE_PACKS_BASE_DIR
Mitigation:
- Preserve these in the injected sensor container definition
- Avoid relying solely on config fields unless the code is updated accordingly
Validation Checklist
attune-sensor-agent --detect-onlyreports detected runtimes correctlyATTUNE_SENSOR_RUNTIMESoverride still takes precedence- Sensor registration records expected runtime capabilities in the
workertable - Sensor heartbeat and deregistration still work
- Python-based sensors execute successfully
- Node-based sensors execute successfully
- Native sensors execute successfully when
nativeis explicitly enabled - Shared
runtime_envsremain usable between workers and sensors docker compose configvalidates cleanly after Compose changes
Deliverables
- New
attune-sensor-agentbinary target - Shared bootstrap/runtime-detection helpers as needed
- Updated agent build/init pipeline producing a sensor agent binary
- Updated Compose deployment using injected sensor agent containers
- Documentation updates covering the sensor agent model