No work step here. This is probably a skill that reads or coordinates, not one that produces something.
.md file to compare - side-by-side diff against now
now
What it does for you
This skill does one job for you, the same careful way every time.
What it produces
A recent result, so you can see the kind of work it returns.
loading…
How to get it
These run inside the Snappy workspace. Want this working in your business? I set skills like this up with you, in one focused week.
For developers how this skill is built, graded, and how it runs
at a glance- the short version
what's inside - the parts that make up a skill 2/4 present
A skill is just a few plain-text files. Only the main one is required. The rest are optional, added as the work needs them. This is what the skill is made of; how it runs is just below.
state/skills/now/SKILL.md
present
state/lib/now.ts
not present
state/bin/now/
not present
state/skills/now/AGENTS.md
present
how it's graded - what counts as a good run 4 criteria · 3 deterministic · 1 judge
Each row is one thing a good run has to get right. deterministic means a quick check decides, pass or fail. judge means the AI reads the result and rates it. Grading each piece on its own (instead of one overall score) shows exactly where a run fell short, so the fix is obvious.
how it runs - the shared frame every skill uses 2/5 present
Every skill runs the same way. One part does the work, a separate part checks it, and a short loader hands the AI exactly what it needs for the job. Anything this skill doesn't use shows a one-line note saying why, on purpose, not by accident.
This skill doesn't fix its own gaps yet.
state/log/evals.ndjson what it has learned - fixes written back in over time sample
When a run hits something this skill didn't handle, the fix gets written back into the skill so it doesn't happen again. FIXED means it was corrected on the spot. LOGGED means it's queued for a bigger rewrite. Either way, the skill gets a little better and never makes the same mistake twice.
- Loading feedback rows…
SKILL.md- the skill, written out in plain English
now
Composite top-level status surface. The current runtime grounds state at dispatch time, then composes an OpenUI surface through compose_inline so the right rail reflects what is happening across skills, agents, and dispatches.
Use this when the user asks broad intent questions like "show me what's happening right now", "give me a system overview", or "show me the status". Do not route through a per-skill .openui file.
Rubric
criteria:
- name: resource_file_exists
kind: deterministic
check: "The runtime can compose a Now surface from live context without a per-skill .openui file."
- name: queries_emit
kind: deterministic
check: "OpenUI Lang includes Query() calls to /agents, /recent, /full-state; all queries complete within 30s timeout."
- name: data_renders
kind: deterministic
check: "Agent activity, recent skill runs, and system KPIs render as Cards with Tables or Stacks; no null/undefined values in display."
- name: dashboard_complete
kind: judge
check: "Dashboard shows all 4 sections (agent activity, recent runs, KPIs, skills summary); metrics are accurate vs actual endpoint values."
The dashboard IS the verb. The chat renders the OpenUI Lang composition generated from live context and can persist it as artifact lang_body if it becomes a reusable Live App.
Dashboard shape
The Now dashboard shows:
- Agent activity - running agents, their status, how long they have been running
- Recent skill runs - the last 10 skill evaluations with scores and timestamps
- System KPIs - total agents, active dispatches, recent activity count
- Skills summary - total skills available, recent skill count
Each panel is a Card with a Table or Stack of key metrics. The dashboard queries multiple endpoints:
/agents- list of agents and their current status/recent- recent skill evaluations (evals.ndjson tail)/full-state- high-level summary of dispatch activity
All data is live; the dashboard refreshes by re-rendering when the user asks again.
No prose steps
The dashboard is purely a UI resource. It has no executable steps - the Steps section is deliberately omitted. The render happens client-side when the snappy-chat app mounts the shape.
AGENTS.md- what the AI loads when this skill comes up
now - loader
Per-turn rules for the live status dashboard. Full skill: state/skills/now/SKILL.md. Live-context-injection skill, eval=auto-shape. No backend execution; the dispatch handler injects fresh JSON and the model composes from it.
Critical Rules
- Live data flows via prompt injection, not at render time. The retired
state/skills/now/resources/ui.openui(deleted 2026-05-11) used OpenUIQuery()bindings that fetched data when the renderer mounted. The new mechanism is the opposite direction:state/lib/live-context-builder.tsdoes the reads at dispatch time and splices the JSON into the system prompt. The model sees freshlistAgents()+readRecentEvals(30)+readAgentsSummary()data each turn, composes Lang viacompose_inline, and the renderer mounts the result. Static Lang, dynamic content.
- Each call produces a different surface. The injected payloads change between calls (last_tick_at advances, recent eval rows shift). Static dashboards that look identical between calls indicate the live-context splice didn't fire. Diagnose: check
state/log/head-screen.logforcache iter=1 prompt_tokens=...- the now-intent path adds ~2400 tokens vs a plain "hello" baseline.
- Regex coverage is narrow on purpose.
isNowDashboardIntent()matches the welcome starter (Show what is running right now, ...), plus shorter variants ("what is running now", "system overview", "what are the agents doing"). It deliberately does NOT match "now I want to..." or "show me the now skill" or "now what?" - those should not trigger live-status data injection. If you add a new intent phrasing, update the regex AND the SKILL.md examples.
- Splice fires in BOTH chat and operator modes. Operator mode includes
liveContextBlockunconditionally (full-assembly path). Chat mode used to skip it for token-bloat reasons; the dispatch handler now opts the now-dashboard turn into the splice viaisNowDashboardIntent(intent)so the welcome starter (which lands in chat mode by default) gets the data. Other chat turns stay lean - no regression to general conversation latency.
- Use the JSON verbatim. The injected envelope says explicitly "use this JSON verbatim; do not paraphrase or invent fields." Composed Lang must reference real agent IDs from the payload, not invented names like "Agent A" or "Worker 1".
Commands
| verb | invoke | input | output |
|---|---|---|---|
| (dashboard) | POST /dispatch/chat with intent matching isNowDashboardIntent | text | streamed Lang compose_inline |
Send any intent matching isNowDashboardIntent() to render. Examples:
- "show what is running now"
- "what is happening right now"
- "what are the agents doing"
- "system overview"
- "give me a status update"
The welcome screen starter card "Show what is running now" fires the canonical phrase.
Self-Test
- [ ] Understand live-context injection happens at dispatch time, not at render time
- [ ] Know
isNowDashboardIntent()is the routing gate instate/lib/live-context-builder.ts - [ ] Know the splice fires in both chat and operator modes
- [ ] Know each turn must produce different Lang because the injected JSON differs
- [ ] Know the model must use real agent IDs from the payload, not invented names
Found a gap? Edit this file. <!-- footer-injection-point -->
api.ts- the code it can call
⚠ no api.ts - this skill has no typed action surface
scripts- helper scripts it can run
prose-only skill - 1 inline code block live in SKILL.md above (no state/bin/ sidecar yet).
how we check it- the checks, plus the last 10 runs
no recent runs logged - the eval contract is declared but nothing has been graded yet