Agent loop
ProAn illustration of the agent loop: gather context, take action, verify, repeat, with a bright head circling three stations around the model.
Agent loop
ReadyFind out why EU cards are declined at checkout, then update the team.
- Fills as the agent gathers context
- Docs, explainers and landing pages that teach how an AI agent works: it gathers context, calls tools, checks the result and repeats until the task is done.
- Showing why agents take several passes, with a failed check or a failed tool call that sends the loop round again.
- A visual summary of a finished agent run with the tools it used and the context it built up.
- Use agent-run or research-run to show a real agent's live steps and streamed output.
- Use tool-call for a single tool call card inside a chat or a log.
- Use reasoning-tree to explain search over thoughts rather than tool use.
- Use mcp-flow to explain how a host talks to MCP servers over a transport.
- Use context-window to show what fills a model's context and how close it is to the limit.
Installation
Pro source and install commands unlock with a Pro plan.
import { AgentLoop } from "@/components/arc/agent-loop/agent-loop";import { GithubMark, SlackColorMark } from "@/components/arc/agent-loop/agent-loop-marks"; export function DeployLoop() { return ( <AgentLoop task="Fix the failing deploy on main and tell #releases." summary="The build cache was stale. Cleared it, the deploy passed and #releases knows." onDone={() => console.log("loop finished")} iterations={[ { gather: { label: "Build log", detail: "Step 4 of 9 failed", tokens: 3200 }, calls: [{ tool: "GitHub", mark: <GithubMark aria-hidden />, action: "Read workflow run", result: "Cache key mismatch" }], verify: { passed: false, note: "Fix not applied yet" }, }, { gather: { label: "Workflow file", detail: "deploy.yml, 84 lines", tokens: 1900, mark: <GithubMark aria-hidden /> }, calls: [ { tool: "GitHub", mark: <GithubMark aria-hidden />, action: "Clear cache and rerun", result: "Deploy passed in 3m 12s" }, { tool: "Slack", mark: <SlackColorMark aria-hidden />, action: "Post update", result: "Posted in #releases" }, ], verify: { passed: true, note: "Deploy green, team told" }, }, ]} /> );}AgentLoop
An illustration of the agent loop: gather context, take action, verify, repeat. A bright head with a soft gradient trail runs clockwise round a ring past three stations, with the model at the center. At Gather context a block joins the context stack beside the ring and the token count rolls up; at Take action a tool call with its real mark drops out of the ring on a short pin and resolves with a result (or an error); at Verify a check passes or leaves a retry note that sends the loop round again. A counter rolls with each loop, and the last one ends in a done state with the ring drawn in, a check at the center and the summary as the caption, or a stopped state when the last check fails. Play, pause, step, restart and speed drive it. The run, the tool calls and their results are sample data; nothing calls a real service.
iterationsAgentLoopIteration[]sample triage run (3 loops)The loops, in order. Each is { gather, calls, verify }: gather is the context block { label, detail?, tokens, mark? }, calls are one to three tool calls { tool, mark?, action, result, status? } shown one after another, and verify is { passed, note }. A failed check reads as a retry note; when the last one fails the run ends as stopped. An empty array shows the ring at rest with the controls off.taskstring"Find out why EU cards are declined at checkout, then update the team."The caption while the loop is ready or running.summarystring–The caption once the loop ends. Defaults to a count of loops and tool calls, or a stopped note when the last check fails (the sample run has its own summary).model{ name: string; mark?: ReactNode } | nullClaude Opus 5.5 with the Claude markThe model at the center. Pass null to show only the loop counter.titlestring"Agent loop"Card title.stationLabelsPartial<Record<"gather" | "act" | "verify", string>>Gather context, Take action, VerifyStation names. Keep them to about two words; a longer name truncates beside its station.autoPlaybooleantrueStarts the loop the first time the card is mostly in view. Under reduced motion the card opens on its done state instead.loopbooleanfalsePlays again about four seconds after the done state.speednumber–Playback speed, controlled. At 1 the sample run takes about 18 seconds; 0 holds still. Pair it with onSpeedChange.defaultSpeednumber1Starting speed when uncontrolled. The control offers 0.5, 1 and 2.onSpeedChange(speed: number) => void–Called when the speed control changes.controlsbooleantrueShows play and pause, step, restart and the speed control.onStationChange(station: "gather" | "act" | "verify", iteration: number) => void–Called when the head reaches a station, with the zero based loop. Fires once per beat, never per frame.onDone() => void–Called each time playback reaches the done state.classNamestring–Class on the root element.styleCSSProperties–Inline style on the root. Set --al-accent to recolor the head, trail, pins and active stations (defaults to --series-1).- Tab
- Moves through play or pause, next step, restart and the speed control.
- EnterorSpace
- On play, pauses or resumes; on next step, plays to the next beat (a new context block, a tool result, a check or the end) and stops there; on restart, starts over from the ready state.
- Arrow leftorArrow right
- On the speed control, moves between 0.5×, 1× and 2×.
- The card is a labelled group. Station names, tool calls, results, checks and context blocks are real text, and the ring drawing itself (track, pins, head) is hidden from assistive technology.
- A polite status region speaks each beat when you step or pause (for example "GitHub returned: EU cards, since Oct 18"), and the summary at the end, but stays quiet while the loop plays on its own.
- Status never relies on color: ready, running, paused, done and stopped each pair an icon with a label; a tool result shows a check or a cross, a failed call says failed to screen readers, and a check shows a check icon with "Check passed" or a rotate icon with "Retry".
- The context list is an ordered list, read in the order blocks were gathered.
- When stepping reaches the end, Next step turns off and focus moves to Restart instead of falling back to the page.
- Pointer focus draws no ring; keyboard focus uses Arc's shared focus outline on every control.
- The head eases from station to station round the ring and drags a soft gradient trail that stretches with its speed and shrinks to nothing when it lands, so it never sits still with a tail. Small chevrons on the track show the direction.
- The active station's node fills, a thin ring settles around it and its label carries a calm shimmer that stops with a clear solid state.
- A tool call drops out of the ring: the pin under Take action draws down in about 180ms, then the chip lands at its end with a 6px drop and a slight scale on a critically damped spring (no bounce), growing from the pin. Its spinner crossfades to a check or a cross as the result fades in. A second call crossfades into the same lane after the old one fades out in 80ms, so nothing reflows. Checks drop from Verify the same way.
- A new context block fades in at the end of the stack with a short drop while the token count rolls up in tabular numerals; the space for every block is reserved, so the card never grows.
- The loop counter rolls its digit up inside a fixed width. Labels such as the status and the caption swap with one short crossfade.
- At the end the ring draws in clockwise in about 760ms and the head fades out. A stopped run leaves the ring neutral.
- Reduced motion opens on the done state. Playing and stepping still work, with no travel and no trail: the head jumps between stations and each change applies in place.
- From a 640px container the context stack sits in a column beside the ring, with the check and the tool call side by side in two lanes, each at the end of its station's pin.
- Narrower, the context stack moves under the ring (two columns between 460 and 640px) and one lane shows the latest tool call or check.
- The ring is laid out in real pixels from the measured width, so strokes and labels stay crisp at every size. Below a 360px ring column the labels drop their icons and shrink, and on the narrowest cards the two lower stations move further down the ring so their labels fit beside them, which holds down to 320px.
- The speed label hides below a 400px container and the controls wrap onto two lines on the narrowest phones.
- The whole run is a pure timeline built once from the iterations, so pausing, stepping and replaying are exact.
- The head and the trail are written straight to the SVG from one requestAnimationFrame loop that runs only while playing or stepping; React renders once per beat, not per frame.
- The trail is one arc path with a gradient whose ends follow the tail and the head; everything else animates transform, opacity or a stroke dash.
- Autoplay waits until the card is in view.
Notes for AI
Give your coding assistant the Markdown reference instead of screenshots.
- Use it to explain how a tool using agent works (gather context, act, verify, repeat), not to stream a real agent's output. Say in the surrounding copy that the run is illustrative.
- Write two to four iterations. Give each a short context label (one to three words), a detail under about 30 characters, a tool call action of two to four words and a result under about 30 characters, so nothing truncates in the context column or the chips. The context stack reserves a slot per iteration.
- Let the last iteration pass its check; earlier ones can fail with a retry note to show why the loop goes round again. Set status: "error" on a call to show a failed tool call followed by a retry in the same step.
- Copy brand marks from agent-loop-marks.tsx or pass any ReactNode with aria-hidden. Mono marks follow the text color; set style={{ color }} for a brand color. Brand marks are sample content, never an implied endorsement.
- The card is a single focused component about 760px wide at most; it puts the context stack beside the ring from a 640px container and under it below that.
The full library index for assistants is at /llms.txt.