Oslo Vibe Coding

Loop Engineering.

From prompts to /goal
No one codes alone.
01 · Where we are — the current state of prompting

Prompting got us this far.

One question, one answer. It's how the whole world met AI — and it's genuinely good at:
drafts & rewrites
explaining things
quick one-shot answers
one exchange
▸ “Summarise this report”
◂ a summary. done.

“The hottest new programming language is English.”

Andrej Karpathy · OpenAI founding member, ex-Tesla AI · 2023
01 · Where we are — the catch

For real work, you become the loop.

You check the answer. You spot the miss. You paste the error back. Again. And again.
Every orange arrow
is your time.
YOU THE MODEL “write the report script” a script — 90% right “it crashes on line 40” fixed — new bug appears “try again…” ⋯ and again ⋯
02 · What a loop is

Give it the goal, not the steps.

The model acts, checks its own result against the goal, and goes again — until the check passes.
GOAL ACT CHECK goal met? yes DONE not yet — go again pass 1 · pass 2 · pass 3 · …
“Agents repeating cycles of work until a stop condition is met” — Anthropic, Getting started with loops
02 · Who works this way
“My job is to write loops.”
Boris Cherny · creator of Claude Code, Anthropic

“An agent is a model running tools in a loop to achieve a goal.”

Simon Willison · independent AI researcher

“There's a new kind of coding I call vibe coding… you forget the code even exists.”

Andrej Karpathy · 2025 — yes, that's where this meetup's name comes from
03 · The theory — four layers of working with AI

Each layer wraps the one before.

01
Prompt
Word the ask well.
02
Context
Hand it the right material — docs, data, examples.
03
Loop
Let it act, self-check, retry. ← tonight
04
Harness
The rails around the loop — tools it may use, limits it must respect.
Same model underneath — the layers change what you get out of it.
03 · The theory — anatomy of a loop

A loop, taken apart.

Goal
what “done”
looks like
⛔ guardrails — max passes · no-progress stop · budget cap
act observe check
not yet → again
⛁ context in — live data · tools · files
Result
the job, finished —
or an honest
“can't, here's why”
A good loop may fail loudly. It may not run forever.
03 · The theory — the four types of loops

Four loops — each hands off one more piece.

Turn-based
hands off the check
you still prompt each round — it verifies its own work
plain prompting
Goal-based
hands off the stop
runs until a verifiable goal is met ← tonight
/goal
Time-based
hands off the trigger
re-runs on a schedule — watches things that change
/loop · /schedule
Proactive
hands off the prompt
a routine owns the whole job — no one asks
routines
source: Anthropic — “Getting started with loops” · claude.com/blog
03 · The theory — why guardrails matter
7-figure
monthly token bills — reported by teams running unconstrained agent loops at scale.
Every extra pass costs. The curve only bends one way — a hard stop bends it back.
hard limits, not good vibes
HARD STOP loop ends here without a stop ↗ PASSES → COST →
illustrative shape — not a forecast
03 · The theory — subagents

Delegate the noise. Keep the focus.

main loop · stays clean
it only ever sees:
“Torggata: 0 bikes, 40 m from a full station.”
sub-task
one answer
subagent · does the grinding
~260 stations swept · scored · discarded — none of it clutters the main loop
04 · Hands-on — writing a goal a loop can run on

Prompting words the question.
Loop engineering words “done”.

1 · VERIFIABLE
“make it good” isn't checkable. “tests pass” is.
2 · BOUNDED
a budget of attempts, always.
3 · REVIEWABLE
it shows its work every pass.
/goal Make the failing tests pass. Run the test suite after every change — that's the check. ← 1 Stop after 10 attempts or if two passes change nothing. ← 2 Log what you tried each pass. ← 3
04 · Hands-on — loops you could run tomorrow

If the job is “check, fix, check again” — it's a loop.

/goal tests pass
Fix code until the suite is green. The classic developer loop.
for the coders
/goal deploy healthy
Watch the rollout, re-test every minute, report only when green — or shout if it isn't.
for the ops folks
/goal data clean
Recheck the spreadsheet, the report, the inbox — flag exactly what changed.
no code needed
05 · The project — a real resource-planning job

Oslo rebalances bikes all day long.

Riders drain some stations and flood others. A planning team watches dashboards and sends vans to shuttle bikes back.
Tonight, a loop does the watching.
Alexander Kiellands plass
11 bikes · 1 free dock — jammed full
≈ 400 m apart · vans shuttle bikes back, all day
Sofienbergparken
0 bikes · 12 free docks — nothing to ride
05 · The project — the goal we hand the loop
/goal Watch Oslo's live bike data. Find a station with 0 bikes within 500 m of one with 3+ free docks — a real rebalancing problem. Narrate every pass. Stop after 15 passes, or if nothing changes for 3 passes. If no problem exists, say so.

One goal.
Everything we've covered, baked in.

type: goal-based — we hand off the stop
verifiable — concrete numbers
bounded — 15 passes, no-progress stop
reviewable — narrates every pass
data: oslo bysykkel open feed
refreshes ~10 s · no api key · read-only
06 · Build — step 1 of 3 · get the data

Ask the city where its bikes are.

Two open feeds: the map of stations, and the live bike counts. Merge them, and we hold the city in one variable.
BASE = "https://gbfs.urbansharing.com/oslobysykkel.no" NAME = {"Client-Identifier": "oslo-vibe-loop"} # our name tag def snapshot(): stations = get(BASE + "/station_information.json") # where they are live = get(BASE + "/station_status.json") # bikes right now return merge(stations, live) # ~260 stations, ~10 s fresh
06 · Build — step 2 of 3 · define the check

Write “done” as code.

This little function is the dispatcher's trained eye — the thing the loop tests itself against every pass.
def rebalancing_problem(a, b): return (a.bikes == 0 # A is empty — nothing to ride and b.free_docks >= 3 # B has room — bikes piled up nearby and distance(a, b) <= 500) # and they're neighbours (metres) # true for any pair in the city → goal met → the loop may stop
06 · Build — step 3 of 3 · visibility + brakes

Every pass visible. Every stop hard.

pass 03 · 19:41:12 · 264 stations · empty: 7 · match: none · requests: 6 pass 04 · 19:41:22 · 264 stations · empty: 9 · match: none · requests: 8 pass 05 · 19:41:32 · MATCH → Sofienbergparken (0 bikes) ↔ 380 m ↔ A. Kiellands plass (9 free docks) stopped: goal met · 5 passes · 10 requests · 0 humans interrupted
max 15 passes no-progress stop request counter = cost meter
Live run
Real city.
Real loop.
The data changed while we were talking — nobody in this room knows tonight's answer yet. Let's find out.
wifi safety net: --offline replays a cached snapshot
07 · What just happened

You watched every concept run.

what you saw in the terminalwhat it was
“find an empty station near a full one”the goal
fetched fresh city data every passact + context
tested every station pair against the rulethe check
15-pass cap · quit if nothing changesguardrails
one printed line per passreviewability
07 · What just happened — and where the project goes next

Same job, four loops. Tonight was rung two.

1
Turn-based
“any problem right now?” — you ask, you eyeball, you re-ask
2
Goal-based
/goal hunt until a real imbalance is found ← what we built
3
Time-based
/loop 10m patrol the network all evening — nobody presses enter
4
Proactive
a routine owns the watching — pings the dispatcher only when a van is needed
rung four is the resource-planning job, delegated — guardrails ride along at every rung
08 · Closing thought

Usage went up.
Trust went down.

The loop can do the work — but the check is yours to design. Review is a choice now. Make it on purpose.
A prompt gets you an answer. A loop with a goal and a guardrail gets you a finished job.
usage ↑ 84% trust ↓ ~⅓ STACK OVERFLOW DEVELOPER SURVEY 2025
Oslo Vibe Coding
No one codes alone.
oslovibecoding.tech
1 / 19
Loop Engineering — /goal
← → to move · F fullscreen