DisSysLab · Micro-Course

Build an office of small specialist agents.
Each agent has one job.

They watch your sources. They brief you. While you work, sleep, travel.

Situation Room — Live Live
CRITICALFed signals surprise rate cut — markets reacting
HIGHOpenAI announces GPT-5 release date
MEDIUMPython 3.14 beta drops with JIT improvements
Sense and respond

This is not a chatbot.

There is no prompt. There is no wait. The office watches your world and acts — while you work, sleep, or travel.

Chatbot
Ask me anything…▌
Waits for you to ask
DisSysLab office
📡 14:02 · News classified
📧 14:01 · Inbox triaged
🔔 13:58 · Alert sent
Acts on its own
A running situation room

An office of specialist agents. This is what you get — live, on your laptop.

🏛️ Situation Room — running right now Live
Briefings — newest first
The complete office

Here's all you wrote.

office.md
Sources
bluesky(max_posts=None, lifetime=None)
al_jazeera(max_articles=10, poll_interval=600)
bbc_world(max_articles=10, poll_interval=600)
Sinks
intelligence_display(max_items=8)
jsonl_recorder(path="situation_room.jsonl")
Agents
Alex is an analyst.
Morgan is an editor.
Connections
bluesky's destination is Alex.
al_jazeera's destination is Alex.
bbc_world's destination is Alex.
Alex's editor is Morgan.
Alex's discard is jsonl_recorder.
Morgan's situation_room are intelligence_display and jsonl_recorder.

No code. Two plain English documents.

The job descriptions

Plain English. That's it.

analyst.md
---
outboxes: editor, discard
adds: importance, summary
---

You are a news analyst who receives posts and articles from social media and news sources. Your job is to assess whether each item is relevant to current world events. If relevant, send to editor. Otherwise send to discard.

editor.md
---
outboxes: situation_room
adds: briefing, priority
---

You are an editor who receives classified articles from the analyst. Your job is to rewrite each article as a concise briefing note with a priority rating. Send to situation_room.

Prose for the job. Four lines at the top declaring the outboxes it may send to and the fields it adds — so the office can be checked before it is run.

What is an office?

An office of specialists.
That never clocks out.

Specialist agents. Cooperating. Continuously.

You describe the agents. DisSysLab handles everything else.

Sources
🦋BlueSky
📡Al Jazeera
📺BBC World
Agents
🔍
Alex
analyst
inbox
0
Watching sources…
↓
✏️
Morgan
editor
inbox
0
Ready…
Outputs
📊Dashboard
💾Archive

Connect any agent to any agent.

Many → One
📰 News
🦋 Social
📡 Feeds
🔍
Analyst
Fanin
One → Many
✏️
Editor
📊 Dashboard
💾 Archive
📧 Alerts
Fanout
How do you describe an agent?

Each agent does one thing.
Describe it in English.

analyst.md
You are a news analyst who receives
posts and articles from social media
and news sources.
Your job is to decide if each item is
relevant to current world events.
Send to editor if relevant.
Otherwise send to discard.
Who they are
What their job is
Where to send results
A specialist's job description

Job Description.
It's that simple.

analyst.md

You are a news analyst who receives posts and articles from social media and news sources.

Your job is to assess whether each item is relevant to current world events — politics, economics, science, technology, or humanitarian issues that a senior analyst would want to know about.

For each item, rate its importance: CRITICAL for breaking news requiring immediate attention, HIGH for significant developments, MEDIUM for notable but not urgent, LOW for background information.

If the item is relevant, send to editor with your importance rating and a one-sentence summary. If not relevant, send to discard.

Two ways to specify a job

English when AI can do the job.
Python when it must be exact.

Most agents are small enough to specify in English. For deterministic work — dedupe by URL, sliding-window RMS, wrap an ML model — use Python. The framework runs both the same way, and both declare their ports: prose in front matter, Python in AgentRoleEntry.

analyst.md
---
outboxes: editor, discard
adds: importance
---
You are a news analyst who decides if each item is relevant to current world events.

If relevant, send to editor.
Otherwise send to discard.
deduplicator.py
def dedupe(msg):
  if msg["url"] in seen:
    return None  # drop it
  seen.add(msg["url"])
  return [(msg, "out")]

role = AgentRoleEntry(
  name="deduplicator",
  in_ports=("in_",), out_ports=("out",),
  factory=lambda: Role(fn=dedupe,
                  statuses=["out"]),
)

The declarations are why dsl check can find a message addressed to an inbox that does not exist — it reads them without importing anything.

Roles are reusable

A role is a job description.
Not a person.

🔍 analyst.md Role
"…if relevant, send to editor…"
used in 3 offices ↓
📰News Office
🔍
Alex
analyst
"Alex's editor is Morgan"
✏️
Morgan
editor
🏆Sports Office
🔍
Jordan
analyst
"Jordan's editor is Sam"
👔
Sam
CEO
🔬Science Office
🔍
Riley
analyst
"Riley's editor is Dana"
🛡️
Dana
security
📚 The analyst role is identical in all three offices.
Only the wiring changes.
The org chart

Name your agents.
Give each one a role.

office.md — Agents
Alexis ananalyst.
Morganis aneditor.
Miais aneditor.
Samis areporter.
Wiring the office

Write one line.
Make a connection.

office.md — Connections
"Morgan's situation_room are intelligence_display and jsonl_recorder ."
✏️
Morgan
📊
intelligence_display
💾
jsonl_recorder
The complete office

The whole office.
One screen. Plain English.

office.md
bluesky(max_posts=None, lifetime=None)
al_jazeera(max_articles=10, poll_interval=600)
bbc_world(max_articles=10, poll_interval=600)
intelligence_display(max_items=8)
jsonl_recorder(path="situation_room.jsonl")
Alexis ananalyst.
Morganis aneditor.
bluesky's destination isAlex.
al_jazeera's destination isAlex.
bbc_world's destination isAlex.
Alex's editor isMorgan.
Alex's discard isjsonl_recorder.
Morgan's situation_room areintelligence_display and jsonl_recorder.
Mix and match

Pick the AI per agent.

Cheap models for routine work. Premium models for the writing. Free local models when privacy matters. One office can use all three.

office.md
Eve's AI is ollama.🦙 free, local
Sam's AI is openrouter.🚦 cheap cloud
Riley's AI is claude.🧠 highest quality
You've got this

Three things.
That's all you write.

Sources and sinks — where data comes from, where results go — you pick from a library. No writing needed.

1
📋
Roles
"You are a news analyst who receives posts and decides if they're relevant…"
2
👥
Agents
"Alex is an analyst.
Morgan is an editor."
3
🔗
Connections
"Alex's editor is Morgan."
That's everything.
Not a DAG

Loops welcome.

Many frameworks force a one-way pipeline. DisSysLab does not. An agent can feed its upstream, feed itself, or wait for a downstream verdict before continuing.

"needs revision" Drafter Reviewer Publisher

Reviewer can send work back to Drafter. A DAG can't.

Checkpoint and resume

Snapshot. Restart. Continue.

Take a checkpoint while the office is running. After a crash, a reboot, or a code fix, restart from the last snapshot. No work is lost.

T0 start office runs · counts events 📸 snapshot state saved to disk 💥 crash dsl run --resume latest continues from snapshot now
Your turn

Install it.
Two minutes.

terminal
$ python -m venv venv $ source venv/bin/activate $ pip install --upgrade dissyslab Collecting dissyslab Downloading dissyslab-1.10.2-py3-none-any.whl ... Successfully installed dissyslab-1.10.2 anthropic-0.39.0 ... $ dsl --help Usage: dsl [COMMAND] Commands: list, init, run, check, draw, roles, grammar, checks, skills, doctor, ...

--upgrade, not install — on a machine that already has an older one, pip install prints "Requirement already satisfied" and changes nothing. Works on Mac, Linux, and Windows.

Pick one

See what's already built.

terminal — dsl list
$ dsl list Available offices (use dsl init <name> <folder> to copy one): periodic_brief Morning HTML brief: news + weather + tickers situation_room Multi-source news → enrichment → digest arxiv_radar Daily arXiv papers → LLM rater → digest kalshi_market_watch Prediction markets → LLM briefing backyard_birds Audio → BirdNET classifier → species labels wildlife_watcher Images → ML classifier → labeled species weather_monitor Hourly plain-English weather briefing stocks_monitor One-line read of a ticker's movement recovery_demo Monte Carlo π estimator with checkpoint-recovery
▶ GIF slot — capture dsl list live in a fresh venv
Copy it

Make a folder that's yours.

terminal
$ dsl init weather_monitor my_weather Copied weather_monitor → ./my_weather Ready. Next: cd my_weather && dsl run . $ cd my_weather
my_weather/
my_weather/ ├── office.md # the wiring ├── README.md # what it does └── roles/ ├── analyst.md # job description └── editor.md # job description

This folder is yours. Edit any file. Run it when you want.

Before you run it

Two commands. One second.

dsl draw — the wiring
$ dsl draw my_weather weather destination ──▶ in_ Alex Alex briefing ──▶ in_ console_printer Alex briefing ──▶ in_ jsonl_recorder
dsl check — the faults
$ dsl check my_weather check_wiring: my_weather/office.md -- 1 problem problem Alex's 'summary' is wired to console_printer, but the role 'analyst' has no outbox called 'summary' -- nothing will ever be sent along that connection. Alex has one outbox, 'briefing'. Write: Alex's briefing is console_printer. what this means: dsl checks W14

dsl draw shows every connection, naming the outbox it leaves by and the inbox it arrives at. dsl check reads the office and reports its structural faults without running it — an inbox nothing writes to, an agent nothing can reach, work that reaches no sink, a message addressed to an inbox that does not exist. dsl checks explains any code it prints.

It is structural, and it stops where structure stops. An office whose diagram is correct can still deadlock. That boundary — what is knowable before you run and what is only knowable after — is the interesting part, and you meet it the first time an office hangs.

One-time setup

Add your API key.

my_weather / .env
ANTHROPIC_API_KEY=sk-ant-api03-xxxxxxxxxxxxxxxxxxxxxx # Paste yours on the line above — no quotes.
Get a key (free trial)
Sign up at console.anthropic.com and create an API key. A few test runs cost under $1.
Keep it private
The .env file is gitignored. Don't paste your key into shared chat, code, or screenshots.
Press play

Run it.
Watch it work.

my_weather — dsl run .
$ dsl run . Starting office: my_weather Compiled network: 2 agents, 1 source, 1 sink Running… press Ctrl+C to stop.
MEDIUMforecast.openweather07:02
Clear skies, 58°F / 14°C. Warming through mid-70s by afternoon.
Morgan: Pleasant day. Light jacket in the morning, short sleeves after noon.
LOWforecast.openweather07:07
No precipitation expected in the next 24 hours.
Morgan: Dry day — good for outdoor plans. UV index 6 (high) from 11am–3pm.
HIGHforecast.openweather07:12
Wind gusts up to 32 mph expected tomorrow afternoon.
Morgan: Secure loose outdoor items. Driving conditions may worsen near 3pm.
▶ GIF slot — capture dsl run . streaming for 30 sec in a fresh venv
Make it yours

Change a prompt. Re-run.

Edit a role file in plain English. Run the office again. Watch the output change.

Before — default role
roles/analyst.md
You are a weather analyst.
Write a short, neutral forecast summary.
Send to editor.
MEDIUMClear, 58°F. Warming to mid-70s.
After — you rewrote one line
roles/analyst.md
You are a weather analyst.
Write a cheerful forecast a runner would appreciate.
Send to editor.
HIGHPerfect running weather — 58°F and clear. Cool start, warming by mile 3.

You're ready.

Build something that actually works for you — an office that watches for exactly what you care about.

📈
Stocks you ownprice swings + one-line take
🔬
New research papersarXiv filtered to your topic
📬
Important emailstriage the inbox while you sleep
🌐
A page you care aboutupdates when something changes