Data Observer vs. Data Agent
This reference document aims to provide a side-by-side look at Observers (data-observer
) and Agents (data-agent
) in Blocktail. Remember, each has its own purpose and scope, yet they collaborate within the Behavioral Layer System—whether you’re coding in plain HTML or a framework like React, Vue, or Angular.
Why We Need Both
Copy link to this sectionSeparation of Concerns
- Observer: Owns a single block (L3), controlling states/mutations (e.g.,
--dark_mode
,--streaming
). - Agent: Applies utility behaviors anywhere—system, context, block, or tail—without messing with block sovereignty.
Clear Ownership
- A block’s observer is the “single source of truth” for its lifecycle and states.
- Agents do not touch the block’s states, so collisions rarely occur.
Key Differences at a Glance
Copy link to this sectionFeature | Observer | Agent |
---|---|---|
Purpose | Manage block lifecycle & states (mutations) | Add utility or cross-layer behavior |
Scope | Block level (L3) only | Any layer (L1–L5) |
Sovereignty | Yes (one observer per block) | No (never claims a block) |
State Control | Handles mutations like --dark_mode , --streaming | Does not handle block mutations |
Lifecycle Events | init() , destroy() , etc. for the block | Optional init/destroy, but no block ownership |
Composition | Can embed “internal modules” or agents internally | Usually self-contained or combined with others |
Conflict Risk | If multiple Observers attach to the same block | Minimal (only if multiple Agents do the same job) |
Example | data-observer="HeroObserver" | data-agent="ParallaxScroll" |
Pattern Evolution & Valid Paths
Copy link to this section1. System-Level Agent + Block Observer
Copy link to this section<body class="matrix--marketing_portal" <!-- L1: System -->
data-agent="GlobalAnalytics"> <!-- Agent for template-wide tracking -->
<main class="context--landing_page" <!-- L2: Local context -->
<section class="hero_banner --dark_mode" <!-- L3 + L4 -->
data-observer="HeroObserver" <!-- Observer for this block -->
data-agent="ParallaxScroll"> <!-- Cross-layer scroll effect -->
<div class="-intro_text">...</div> <!-- Tails (L5) -->
</section>
</main>
</body>
- Observer: Controls block states (
--dark_mode
). - Agent: At system level (
GlobalAnalytics
) plus an Agent at the block (ParallaxScroll
).
2. Multiple Agents, Single Observer
Copy link to this section<article class="live_feed --streaming"
data-observer="LiveFeedObserver"
data-agent="FadeInAnimation">
<div class="-chat_panel"
data-agent="AutoScroll">
<!-- Chat messages -->
</div>
</article>
- Observer:
LiveFeedObserver
(handles--streaming
states). - Agents:
FadeInAnimation
at the block levelAutoScroll
at a tail element
3. Context & Mutation Mix
Copy link to this section<div class="context--premium_users">
<section class="profile_card --vip_access"
data-observer="ProfileObserver"
data-agent="RevealAnimation">
<h2 class="-username">Jane Doe</h2>
</section>
</div>
- Local context
context--premium_users
. profile_card --vip_access
block with a single observer controlling user state + an agent for some animation effect.
Layer Validation
Copy link to this sectionLayer | Observer | Agent | Comment |
---|---|---|---|
L1: Matrix | No | Yes | Observers can’t own <body> , Agents can. |
L2: Context | No | Yes | Observers can’t own <main> or contexts. |
L3: Block | Yes (1 per block) | Yes | Observer owns block states, Agents add utility. |
L4: Mutation | N/A | Yes (optional) | Agents may respond but don’t define states. |
L5: Tail | No | Yes | Observers can’t attach to tails; Agents can. |
Working Together: Observer + Agent
Copy link to this sectionValid Example
Copy link to this section<section class="hero_banner --highlighted"
data-observer="HeroBannerObserver"
data-agent="ParallaxScroll">
<div class="-intro_text">
<h1 class="-headline">Introducing Our New Feature</h1>
</div>
</section>
- Observer:
HeroBannerObserver
manages block states (--highlighted
). - Agent:
ParallaxScroll
is a purely additive effect here.
Tips for Collaboration
- Avoid Overlaps: Agents don’t attempt to handle the same states the observer manages.
- Shared Lifecycle Hooks: Observers handle block-level events; agents may have an
init/destroy
but never override the observer’s flow. - Minimal Cross-Talk: Keep each behavioral pattern (observer vs. agent) self-contained.
Example Code Flow
Copy link to this section<body class="matrix--admin_portal" <!-- L1 -->
data-agent="GlobalAnalytics"> <!-- System-level agent -->
<main class="context--dashboard_panel" <!-- L2 -->
data-agent="InfiniteScroll"> <!-- Context-level agent -->
<article class="live_feed --streaming" <!-- L3 + L4 -->
data-observer="LiveFeedObserver" <!-- Observer for streaming states -->
data-agent="FadeInAnimation"> <!-- Additional block effect -->
<div class="-chat_panel" <!-- L5 -->
data-agent="AutoScroll"> <!-- Tail-level agent for chat scrolling -->
<!-- Chat messages go here -->
</div>
</article>
</main>
</body>
Key Takeaways
Copy link to this section- Observers (B1):
- Single block-level authority
- Handles lifecycle, states (
--dark_mode
,--featured
), resource usage - Composes advanced internal behaviors if needed
- Agents (B2):
- Utility at any layer (L1–L5)
- Never owns block or toggles block states
- Great for shared or cross-layer enhancements
- Predictable Evolution:
- One observer per block → stable states
- Agents can appear anywhere → easy additions
- Large or mission-critical systems remain organized
- Framework-Agnostic:
- HTML attributes keep code flexible in Next.js, React, Vue, Angular, etc.
- Observers and Agents can map to your component lifecycle if desired
- Minimal Confusion:
- Observers unify block logic; Agents offer purely additive functionality
To reiterate, Observers guarantee each block’s logic remains unified. Agents provide cross-layer enhancements without overshadowing the observer’s domain. This ensures clean layering of advanced features in the Blocktail framework.