Separate sensing, state, decisions, and effects
How to study this lesson
Read one section, trace the worked example, and try the knowledge check. Bookmark saves a shortcut; notes appear in My notebook. Mark lesson complete is your own assessment and does not mark its lab passed.
By the end, you can
- Assign responsibilities to architectural components.
- Represent observations without silently turning them into facts.
- Trace one control cycle with explicit state transitions.
Architecture is about responsibility
A cognitive architecture is useful to an engineer when it specifies how information and control move among components. It does not require claiming that software experiences perception or memory like a person. CoALA organizes language-agent designs around memory, actions, and decision processes; established systems such as Soar provide another concrete reference for separating architectural mechanisms. Use these frameworks to ask precise design questions, not to decorate a diagram with human-sounding labels.
In a service assistant, perception parses incoming alerts and tool results. Working state holds the current incident and unresolved questions. Memory supplies relevant prior records. A decision component selects the next permitted action. An executor performs it and returns an observation. A verifier checks completion. Each boundary should have an input type, output type, and accountable failure behavior.
Perception includes interpretation choices
An alert saying latency high is not a complete world state. The parser must identify the service, metric definition, measurement window, timestamp, and source. If a monitoring system reports a ten-minute average, treating it as an instantaneous measurement can produce the wrong response. If a field is missing, preserve that absence instead of guessing a default that changes the incident's meaning.
A practical observation record separates raw content from normalized fields and interpretation confidence. Store latency_ms=900, window_seconds=600, and the observation time, while retaining a source reference. Normalization makes downstream code reliable; provenance makes it possible to inspect an interpretation later. The same raw alert may be reprocessed after a parser correction without pretending the original observation itself changed.
Working state is a bounded model
The agent cannot hold the entire environment. Its working state is a task-specific model: affected service, current hypothesis, known measurements, attempted actions, budget, and completion status. Design it around decisions the system must make. A field that never influences policy, verification, or reporting may not belong in the active state, even if it seems descriptively interesting.
Suppose an alert arrives at minute ten describing a measurement from minute two. A maximum age of five minutes makes that observation stale for immediate remediation. The state should retain the alert for context but mark that fresh measurement is required. Staleness is not falsity. A historical observation can be accurate about its original time while unsuitable for deciding the current action. This distinction prevents old incidents from triggering new mutations.
One cycle with explicit ownership
Trace an incident through one cycle. Perception reads a latency observation. The state reducer records it and computes age. The memory component retrieves a prior timeout incident as a possible analogy. The decision component chooses refresh_metric because current evidence is stale. The executor requests a fresh reading. The reducer adds the returned reading, and the verifier checks whether the diagnostic question is now answerable.
The prior incident is context, not proof that the same cause has returned. The executor cannot mark the whole investigation complete simply because its refresh call succeeded. The reducer should accept only documented event types, so arbitrary tool text cannot write directly into privileged control fields. These ownership rules let each component remain small while protecting the integrity of the overall loop.
Modularity earns its cost through inspection
Separating components adds interfaces and may increase orchestration overhead. It is worthwhile when the boundaries enable replay, independent tests, policy enforcement, or replacement of one model without rewriting everything. A tiny deterministic workflow may need only a state object and two functions. Avoid constructing a large framework before identifying the failures it must isolate.
The code models perception and policy with an immutable observation. A stale measurement selects refresh; a fresh high reading selects inspection; a normal reading selects monitoring. These hand-written thresholds are teaching policy, not trained cognition or validated operational guidance. Extend the example by storing the selected rule and source timestamp in a decision record. That artifact explains behavior more reliably than asking a model to narrate a plausible reason after execution.
Work through the code
An immutable record holds one normalized observation and its provenance. Policy uses observation age before the latency threshold. The minute units and threshold are synthetic teaching choices; no real monitoring API or trained model is involved.
from dataclasses import dataclass
@dataclass(frozen=True)
class Observation:
service: str
latency_ms: int
observed_at: int
source: str
def choose(observation, now, max_age=5):
age = now - observation.observed_at
if age < 0:
return "reject future timestamp"
if age > max_age:
return "refresh metric"
if observation.latency_ms > 800:
return "inspect configuration"
return "continue monitoring"
old = Observation("checkout", 900, 2, "monitor-A")
fresh = Observation("checkout", 900, 9, "monitor-A")
print(choose(old, now=10))
print(choose(fresh, now=10))
refresh metric inspect configuration
Run Python snippets locally with the prerequisites named above. The module coding lab runs directly in your browser.
Pause and reason
A memory component retrieves a previous outage caused by a missing timeout. The current alert has the same service name but no configuration evidence. Which component may use the memory, and what should it avoid concluding?
Check your understanding
A ten-minute-old measurement is accurate about the past but too old for the current decision. How should it be represented?
Your notes
Explain the mechanism in your own words. Add a failure you want to test.