# Environment

> Interpret environmental sensor readings and sustained changes for room comfort and air quality. Use for [environment:initial] greeting context, [environment:update] events, questions about room temperature, humidity, measured CO2 or air quality, checking changes after ventilation or air cleaning, and optional room context when a user reports discomfort. Requires the environment capability. Link to wellbeing for considerate proactive advice; do not diagnose health conditions or infer CO2 or oxygen from other measurements.

- Skill: `autonomous-ai/environment` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add autonomous-ai/environment`
- Raw SKILL.md: https://api.skillmd.com/api/skills/autonomous-ai/environment/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: autonomous-ai (https://skillmd.com/u/autonomous-ai)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/autonomous-ai/environment

---


# Environment

## Scope and data

Work from the device's declared `environment` capability and the measurements actually present. Do not require a camera, microphone, emotion marker, or a particular sensor model. If the capability is absent, skip environmental checks; explain unavailability only for an explicit room-data question. Do not enable hardware or edit its declaration.

For a direct room question, a requested current comparison, or optional room context for a wellbeing concern when the capability is declared, read the OS environment status API once (reuse a supplied current status snapshot when available):

```bash
curl --fail --silent --show-error --max-time 5 http://127.0.0.1:5000/api/environment/status
```

This read-only route admits local device callers and checks the environment capability. It returns the OS envelope `{"status":1,"data":{...HAL snapshot...},"message":null}`; inspect `data`. A non-2xx response or `status:0` means unavailable. Do not bypass a denial through HAL or fetch credentials for the browser's authenticated hardware proxy.

Use the existing snapshot in an automatic event unless it is stale or the user explicitly requests a fresh check. Do not run a polling loop, start a cron job, invent a history endpoint, or promise a timed follow-up: OS owns polling, thresholds, sustained-change detection and cooldowns.

A usable snapshot has `enabled: true`, `state: "ready"`, `stale: false`, and at least one fresh numeric measurement in `sample`. The shared status sample always contains nine nullable metric keys; an object of null values is not usable data. Check `age_s` and `sample.timestamp` before describing it as current. Disabled, starting, stopped, error, missing or stale data is unavailable, not zero pollution. Say so briefly on an explicit room-data question; stay silent on an unusable automatic event. For a wellbeing concern, silently skip unavailable environmental data and continue support without sensor-error commentary. Individual null or absent measurements are unknown: retain the other valid readings. For a multi-component snapshot, `sources[metric]` identifies its entry in `components`; check that component's state, age and stale flag, plus `metric_timestamps[metric]`. The aggregate timestamp may belong to another sensor and does not establish freshness for every field. One failed component does not invalidate another healthy component.

| Sample field | Meaning |
|---|---|
| `pm1_0_ug_m3`, `pm2_5_ug_m3`, `pm4_0_ug_m3`, `pm10_ug_m3` | Particle mass concentrations, µg/m³ |
| `temperature_c` | Temperature near the installed sensor, °C |
| `humidity_pct` | Relative humidity, % |
| `voc_index`, `nox_index` | Relative gas indices, not gas concentrations |
| `co2_ppm` | Measured carbon dioxide concentration, ppm, when a CO₂ component is available |

Interpret the available metric, independently of the component model. Unsupported metrics are null, just like currently unavailable readings; use component state and `sources` for diagnostics, not the null alone. A healthy component without VOC/NOx is normal and does not require waiting for those indices or reporting a fault. Missing CO₂ does not prevent using valid PM, temperature or humidity. CO₂ is distinct from CO and O₂; the supported measurements do not include those gases. Use CO₂ only when its own reading is fresh, never estimate it from VOC/NOx. Do not infer oxygen shortage, impaired cognition, a gas leak, a fire or a medical condition from environmental readings.

VOC Index adapts to recent history (roughly 24 hours, baseline 100); NOx Index uses a different baseline (1). Neither baseline certifies safe air. Do not identify a chemical, smell or pollution source from either index. Describe an increase relative to previous readings. Do not convert indices into ppm or apply concentration guidelines to them. Instantaneous PM readings cannot establish compliance with 24-hour or annual WHO exposure guidelines. Sensor temperature may be affected by the enclosure and nearby electronics; do not present it as body temperature or a guaranteed room-wide measurement.

## Event contract

`[environment:update]` is followed by an OS-generated JSON object containing
`observed_at` (Unix seconds), `sample` (measurements and timestamp), `changes`
(keyed by metric, each with `previous`, `previous_at`, `current`, `current_at`, `delta` and optional `source`), `sustained_s`, and per-metric `sources` / `metric_timestamps`. Older events may omit the added provenance fields.
Use the numeric change facts rather than guessing a trend from one raw sample.
Do not assume the event has the full status envelope or all metrics. A delayed
event describes its observation time, not necessarily the current room; obtain
current status before giving time-sensitive advice. `previous` is the detector's
previous acknowledged baseline and `previous_at` is its Unix timestamp;
`current_at` is that metric's observation time; `observed_at` is the newest valid reading in the snapshot and may belong to a different component. For older single-sensor events without `current_at`, use `observed_at`. `current` is the latest sample, not a rolling
average. `sustained_s` describes consecutive qualifying readings, not a health
exposure assessment. Missing context does not
justify invented thresholds, durations, health classifications or user activity.

An initial report has `reason: "initial"`, `changes: {}`, and only the metrics
that have passed OS freshness and warm-up checks. It is either embedded in the
startup greeting under `[environment:initial]`, or sent after the greeting as
`[environment:update]`. It is a first observation, not a significant-change
alert: empty `changes` is expected. Other metrics may still be warming up.

## Discomfort and ventilation context

When the user says they feel tired, headachy, dizzy, stuffy or unable to focus,
consult `skills/wellbeing/reference/discomfort.md` for the response. Apply it
here without handing the turn back through the wellbeing activity router.
Do not inspect sensors before responding to an already apparent urgent symptom
or reported exposure. Otherwise use at most one status read, only when the
capability is declared. A failed read, all-null sample, stale data or absent
metric means omit that environmental explanation, not invent a substitute.

Separate three facts: how the user says they feel, what the sensor measured,
and which action might improve comfort. An increase is not itself a high or
harmful concentration. Two event endpoints or `sustained_s` do not establish a
long-term concentration average. For context only, HSE workplace guidance
flags CO₂ consistently above 1500 ppm in occupied rooms as a reason to improve
ventilation. This is not a symptom-causation threshold, universal home safety
boundary, or a new OS alarm rule; do not claim consistency from one sample.
See [HSE: using CO₂ monitors](https://www.hse.gov.uk/ventilation/using-co2-monitors.htm)
(reviewed 2026-09-14). State a lone value as a current observation, and use
available context before suggesting action. Readings can be affected by
placement, nearby breath and calibration; do not label the room safe from a
low CO₂ value or diagnose poisoning from a high one.

For rising measured CO₂ with a useful ventilation opportunity, suggest one
practical option: an outside-facing opening when outdoor air/weather allow,
a fresh-air ventilation setting, or moving to a more comfortable ventilated
space. An interior door alone may not bring in outdoor air. Do not invent
outdoor air quality from indoor PM or fetch unrelated services to manufacture
certainty. If outdoor smoke/pollution or unsafe access makes opening a window
unsuitable, choose another option. Recirculation/HEPA is not CO₂ removal.
[HSE: improving ventilation](https://www.hse.gov.uk/ventilation/how-to-improve-ventilation.htm).

## Choose the response

1. **Direct room-status question:** report the most relevant available measurements and an evidenced trend, usually in one or two sentences. Give numbers when useful or requested. A single snapshot cannot establish a trend or that the whole room is safe.
2. **Initial report (`reason: "initial"`):** use the supplied snapshot to add at most one short factual sentence with one or two useful readings. In `[environment:initial]` greeting context, preserve the normal greeting and do not create another turn or fetch/wait for sensor data. Without usable greeting context, just greet normally. For a separate initial update, skip a second greeting; a simple observation can be useful even without a change or advice. If delayed data is no longer current, omit it rather than refresh or poll for this startup report. Respect quiet/sleep preferences with `NO_REPLY` for a separate update; in a greeting omit only the environmental sentence. Do not claim improvement, a trend, safety, or health effects from this first snapshot. OS owns one-time delivery and retries; do not schedule another report for missing or warming metrics.
3. **Automatic changed `[environment:update]`:** use the supplied change facts. A significant change means OS's configurable change policy fired; it is not automatically a harmful level. Consider whether the change merits action using the environmental-care section of `skills/wellbeing/SKILL.md`. If there is no useful new advice, output exactly `NO_REPLY`.
4. **After an action:** compare a fresh value with an actual earlier, timestamped value in the event or conversation. State the observed direction without claiming causation: “Particles are lower than before.” If there is no comparison point, say that a change cannot yet be established. A later significant-change event may support an update, but no event is a guarantee of scheduled follow-up.

Do not route environmental updates to sensing's camera/presence reaction matrix or guard alerts, even while guard mode is active. No mandatory emotion, servo, light, camera or speech action. An environmental event alone never establishes a person’s presence or authorizes a greeting; startup context only supplements an already requested system greeting. Process only this event; it does not authorize resuming an unrelated task.

## Useful, proportionate advice

- Increased particles: suggest checking an identifiable source or using an available particle filter. Do not assume cooking, smoking, occupancy or a fire without supporting context.
- Measured CO₂ increase: describe its value and supported trend; suggest checking ventilation when outside conditions allow. A recirculating fan or HEPA particle filter does not lower CO₂ by itself. The configured CO₂ delta is a change trigger, not a health limit; do not claim a cognitive effect or diagnose symptoms from a reading.
- Gas-index changes: suggest checking recent activities or sources; ventilation may help when outdoor conditions allow. A HEPA particle filter does not remove every gas.
- Temperature or humidity: offer a modest comfort adjustment when supported by readings and user preferences. Do not diagnose dehydration, illness, sleep quality or productivity from the sensor.
- Do not blindly recommend opening a window when outside pollution or weather is unknown. Phrase that condition explicitly when relevant.
- Recommend actions; operate a fan, purifier, humidifier or HVAC only through an available integration under the user's authorization. Do not invent actuator APIs or promise devices that are not connected.
- Respect requests to stop reminders. Do not change detection policy or disable the sensor merely because a reading is inconvenient.

## Coordination with wellbeing

Read `skills/wellbeing/SKILL.md`'s **Environmental care** section for proactive phrasing and timing. Environment owns measurement interpretation; wellbeing contributes the user's preferences and available activity context. This is a one-way consultation of that section, not a handoff back through its activity router; do not bounce between the two skills. No activity logs, camera observations, identity or hydration/break counters are required to answer a room question. Do not fabricate a wellbeing context block or log an unsupported `nudge_environment` action.

When speaking proactively, offer one useful observation and at most one action in the user's language. Keep analysis and skill names out of the spoken reply. Silence is the literal `NO_REPLY`, without an explanation or hardware markers.


## Example decisions

| Input | Response direction |
|---|---|
| “How is the room?”; temperature valid, VOC null | Report temperature and other valid readings. Do not turn null into zero or assume missing VOC means hardware failure. |
| Cold boot; greeting has no environmental context | Greet normally without waiting, checking the API, or claiming missing readings are zero. |
| Warm HAL; greeting includes initial temperature and CO₂ | Add at most one factual sentence using supplied fresh readings; no second notification. |
| First update has `reason: "initial"`, `changes: {}`, temperature only | Briefly report temperature when appropriate; do not require a delta or wait for VOC/NOx. |
| Delayed initial update; readings are stale or unavailable | Omit the environmental report (`NO_REPLY` for a separate update); do not fetch or promise a retry. |
| “I feel tired and have a headache.” | Use wellbeing’s discomfort reference. When the environment capability and fresh readings are available, optionally add one relevant observation; otherwise omit environment entirely. Never assign a cause from sensor data. |
| CO₂ component stale; PM fresh | Report PM if useful; CO₂ is unavailable. Do not reuse the aggregate timestamp to call CO₂ current. |
| CO₂ rises after a particle purifier starts | Explain that particle filtration does not address CO₂; consider ventilation conditionally, without assuming occupancy or health effects. |
| VOC Index returns to 100 | Describe the relative change if relevant; never say pollution has cleared or air is safe. |
| Automatic change while context says the user is asleep or wants quiet | `NO_REPLY`; do not wake them, trigger guard mode or emit an emotion marker. |
| “I turned the purifier on; is it helping?” | Read current status and compare with a real earlier value if available. Without one, give the current reading and explain the missing comparison. Do not promise a timed recheck. |
| Delayed event or stale status | Do not describe old measurements as current. A failed fresh check means current conditions are unknown. |

