DGC v0.48.4 is out
Navigate
Install DGC
DGC v0.48.4Edit on GitHub ↗
Features/Sub-agents

every sub-agent this chat started, and what each one is doing

Sub-agents

#

The model can hand part of a job to a sub-agent with its task tool: a separate agent with its own context that does the work and reports back. A delegated step can take minutes, so DGC shows every sub-agent the chat has started and what each one is doing, instead of one spinner.

Named agents and trust

#

Five specialists are always available as the task tool's agent argument:

  • explorer — read-only search and map of the codebase (no writes).
  • researcher — investigate and write one findings file, then stop.
  • critic — review named files or a change; correct them or list blocking issues.
  • verifier — try to prove a claim or a change wrong: it reads and runs the tests or commands that would show it, edits nothing, and starts its answer with CONFIRMED, REFUTED or UNSURE.
  • worker — implement a bounded change (the default when agent is omitted).

The main agent is offered task when you ask it to delegate or to survey the codebase, and on every turn under Ultra; a sub-agent is offered it only when its own brief asks, so work does not fan out recursively. The roster above, plus your own definitions, is listed to the model only while task is offered. After a researcher writes a design or plan file, the main agent should spawn critic on that path before implementing, unless you asked it to skip review. When a child finishes, the main agent reports in one or two sentences and names the files; the child's logs stay on that agent. In the editor each specialist is a coloured identity chip in the thread: the mark moves while it works and stills when it finishes. Click the chip (or its row in the agents list) for that agent's own page — duration, answer, and files. Child greps and edits do not dump into the parent chat.

task accepts background: true so the child keeps working after the current turn ends. An interactive Ultra fan-out defaults its omitted background flags to true, so after launching two or more independent children the parent remains available for your steering and for other independent work. Set background: false explicitly when its next model step really needs the result; a single task still defaults to foreground. The composer stays free. The agents pill remains while that specialist runs. When it lands, DGC starts a wake turn with the child's summary in the editor, and in the terminal while wake-ups are on; elsewhere the result reaches the model between tool calls or with your next message. Either way you do not sit in a blocked turn polling it, and wait_tasks collects it the moment you need it. A dgc -p run ends with its turn, so there a background child is for overlap within the turn: one still running at the end is stopped. Foreground task (the default) still waits.

You can change that while it waits: Run in background moves a helper the turn is waiting on (or a bash command still running) to the background. Press Ctrl+B in the terminal (with several, it asks which, or All), or Run in background on the helper's line in the editor's chat, its card in the agent map, or the command's row. The turn stops waiting and carries on; nothing restarts. The helper becomes a background helper, exactly as if it had been started with background: true: the agents pill counts it, its changes land when it finishes, and its finish wakes the chat with its report. A command becomes a background command (bg3) with everything it printed kept, and its exit wakes the chat. One helper of a batch can be moved alone; the batch's result says so and the rest finish as before. Once moved, Stop on the turn no longer reaches it: stop it from its own row, the agent map or the background list. The model is told that you moved it, to carry on without it, and not to start it again. Not in dgc -p, and not for python, whose interpreter the next call needs.

That wake turn opens with one quiet line per finished child, "Woke on agent · Review billing.py", folded, never a message from you. Open it (click it, or Enter or Space in the editor; /expand in the terminal) for the child's whole report: what became of its changes (completed and integrated, partly integrated, or not integrated and where its worktree is kept), then what it said and the files it named. In the editor the report also has Open in agent map, which opens the map at that child's card. A reopened chat draws the same lines, and so do the places that read a conversation back: /export and /copy all write it as DGC's line with the report under it, "Show earlier messages" shows it under DGC, and a compaction's summary never counts it as something you said.

One task call can also start several helpers at once: tasks lists 2 to 8 of them, each with its own description, prompt and agent, and they start together (some models send one task call per reply even when they mean several, so their helpers used to run one after another). Without background, the call returns when every helper has ended, with each one's result under its own description, in the order listed, a failed one included; with background: true it returns at once with every helper's id. They run up to max_parallel_tasks at a time and the rest wait for a free slot. Each has its own private checkout, and their changes land or are kept aside exactly as several task calls in one reply would. Stopping the turn stops every helper the call is waiting for; background helpers run on, as a single background task does, and stop from the agent map.

A background child belongs to the chat that started it. Starting a new chat — /new, /clear, or the editor's New Session — stops any that are still running and says how many, because the chat that asked for the work is gone: a child left running would keep writing files and would fold its worktree back in against a conversation that never asked for it, putting those edits inside the reach of the new chat's /rewind. Switching between two open chats does not stop anything — each chat has its own backend, and a background child running in the one you switched away from is exactly the point.

Personal definitions in ~/.dgc/agents/ are available in any workspace and override a built-in of the same name. A project's .dgc/agents/ definitions load only after you trust that project, because a definition can select its own model host and an environment key. Trusting an already-open terminal or editor loads them without a restart. Isolated tasks and fleet workspaces use the approved source project's definitions rather than loading new definitions from their scratch checkout. An optional tools: frontmatter line is an allow-list of built-in tool names.

Watching, and waiting on purpose

#

A foreground task blocks until the child is done. A background: true one does not, and its result arrives on its own (a wake turn in the editor and the terminal, otherwise with the next message). Between those two the model was blind: it had started something detached and had no way to ask about it.

Four tools close that. None is offered unless there is something to act on — a background child still running, or one whose result nobody has read yet — so a pointless wait is not possible. Neither is offered in a session whose host application set its own tool allowlist either: that allowlist could not have named them, and a policy that could not have named a tool never silently receives it.

  • list_tasks — every sub-agent of this chat, from the same snapshot the agents pill and /agents read: its id, its state (queued, running, waiting on the user, finished, failed, stopped), how long it has run, its tool count, and a finished one's one-line summary. A child started by another child is indented under it. Instant, and it marks which results are still unread.
  • wait_tasks — block until a background child reaches a final state, then hand back its whole result: the same text a foreground task would have returned, including which paths were integrated. ids takes the ids list_tasks gave; leave it out to mean every background child of this chat. Either way it returns as soon as the first of those has a result nobody has read. timeout_s is 30 seconds by default and is clamped to 5–600 rather than refused. Four results come back at once; the rest are announced and wait for the next call.
  • message_task — one message into a child that is still working, of one of two kinds. By default a correction: a constraint that was left out, a narrowing of the brief, something the child is getting wrong. With adds_work, more work: what the child is already doing still stands, and this is added to it. The child is told which, in so many words — before, everything arrived as a correction, so a parent adding scope told the child the opposite of what it meant. Either way it is folded in at the child's next tool boundary: it starts no new task, restarts nothing and waits for nothing, and a child that has already finished cannot read it — the answer says so and points at wait_tasks (and continue_task gives a finished one more work, below). The two control tools need a child that is still RUNNING, not merely a result nobody has read. The transcript names the child by what it was asked to do: Sent message to Write the parser, in the editor (and again when the chat is reopened there) and in the terminal UI as it happens.
  • close_task — stop a child whose work is no longer wanted. Its changes are not integrated: whatever it had written to its own checkout is preserved as retained work, so /tasks can apply or drop it, and nothing is silently thrown away. Stopping a child stops anything it started. It returns as soon as the child is signalled; the child's own account arrives the usual way.

The same two actions are available to the USER over the wire, as agent_control — so a background child that is going wrong can be stopped on its own instead of ending the whole turn.

A wait ends early if you say something while it is running, and says so, so the model reads you before it reads the child. A timeout reports what is still running and tells the model to get on with something else meanwhile. Waiting on an id that ran in the foreground is an error that explains itself — that task already returned its result — rather than a silent wait on nothing.

A result the model read inside its turn is not announced again afterwards. The wake-up that would have repeated it is dropped, so one child is reported once instead of twice.

Neither tool reaches a sub-agent: a child's background: true runs inline, so a child has nothing detached to supervise. Neither can be named in a permission rule, because neither changes anything — deny: Task is the off switch, and with no children the pair never appears at all. Repeating the same wait_tasks call is how waiting works, so it is exempt from the loop guard that stops a model reissuing an identical call.

Both show their work as they run: Checking sub-agents, and Waiting for a sub-agent with a line every five seconds — waiting on 2 background sub-tasks · 15s of 30s.

Asking a finished helper to do more

#

A helper that has finished can be given more work, and it is the same helper that does it, with its memory of what it was asked, what it read and what it found. A review can become its fixes, then a follow-up fix, without a new helper reading everything again.

  • You: on a finished helper's card in the agent map, or under its report line in the chat ("Woke on agent · …"), type into Ask it to do more and press Continue (or Enter). In the terminal, /agents continue <id> <what to do>; /agents shows the id to use beside each helper that can be continued ("continue 1a2b3c4d"). It runs in the background, the chat stays free, and its report comes back like any background helper's.
  • The model: continue_task with the helper's id and the new request, in the turn like task or with background: true. It is offered only when a helper of this chat can be continued, and it is asked for exactly as a task for that helper is (in Default mode you approve it; deny: Task refuses it). For a helper that is still working, message_task is the tool.

How it picks up:

  • From its saved conversation. When each of its runs ends, DGC keeps the helper's conversation beside the chat's saved session (in <session>.helpers/, private and with secrets removed, like the session itself), so a reopened chat or a restarted DGC can continue it. A chat that is not saved keeps it for as long as the chat is open. A run that a restart stopped part-way has nothing saved (Run again starts it fresh), and a helper's own helpers are not kept. Deleting the session deletes them.
  • In a fresh copy of your project as it is now, isolated like any helper: its old copy was brought in and removed. It is told which files of the project changed since it last saw them, and to re-read a file before editing it.
  • Compacted first when its conversation fills half its window or more, with DGC's own compaction, before the new request is added.
  • On the same agent and model as before, with the chat's permissions.
  • Work that was held back (waiting in /tasks) is shown to it as a diff, in the fresh copy; its kept worktree stays where it is until you apply or drop it.

The agent map keeps its one row, now "Continued · 2 runs", and its transcript shows each run after a divider: what the run before reported, "Continued 18:42 · asked by you", and what it was asked. Its changes are brought into your checkout, and taken back by Undo, like any helper's. A helper never writes into a file you have uncommitted work in; a file it changed itself in an earlier run, that nobody has touched since, is its own work, so its next change to that file lands too.

Eyes for a model without vision

#

If the chat's model cannot read images (for Ollama, vision is missing from its capabilities in ollama show), DGC finds a model that can and lets it do the looking:

1. the sub-agent model (/subagent model NAME, with /subagent host URL if it runs elsewhere), when its capabilities include vision; 2. otherwise a named agent whose model has vision: one named viewer first, then the others by name; 3. for a sub-agent whose own model cannot see, the chat's main model when it can.

A look is one request to that model with the image and a question. It uses no tools, no checkout and no agent loop, so a vision model that cannot call tools (qwen2.5vl, llava) works too. The answer comes back as text the chat's model works from:

  • An image you attach to a prompt is looked at before the turn starts, with your prompt as the question. The chat shows a view_image step, attached image · via qwen3-vl:8b (sub-agent model); open it to read what that model saw. The picture stays in the conversation, and the chat's model receives that report in its place on every later request too. If you switch to a model that can see, it gets the picture itself.
  • An image file in the workspace. view_image is still offered, with a question argument: the chat's model asks what it needs to know ("which elements overlap, and what text do they show?"), and the step's output names the model that looked and gives its answer. read_file on an image works the same way, with a general describe-everything question. A browser screenshot says where it was saved so the model can ask view_image about it.

A model's capabilities are read once and cached (capability_cache_ttl_s, 5 minutes by default), never checked on every request. Only positive evidence counts: an Ollama model has to list vision, and an endpoint that turns out to refuse the image is dropped. With no vision model available, DGC keeps the old behaviour: the image reaches no model, the model is told it exists, and you get one line saying how to set up a vision sub-agent model.

The count

#

The prompt area lists every sub-agent started in the current turn — queued, running, waiting, finished, failed or stopped — so you can see the whole batch while work is happening. When the turn ends the count clears, unless a specialist was started with background true: that one stays in the prompt until it finishes, and DGC starts a new turn when it lands. Completed work stays in the transcript; it does not inflate the count as a chat gets longer.

You can change the model while a turn is running. A round that is already answering keeps its client; the next model round uses the new one. A round that has not produced anything yet (the old model still loading, queued upstream or stalled) is sent again to the new model at once, and the chat says so. The chat records Switched to <model>. Thinking works the same way: Settings → General → Thinking is the composer dial. Changing it mid-turn keeps the current request's level and uses the new level (and its guidance) from the next model round. The chat records Thinking → high. If you stop a turn and pick a vision-capable model, the next turn can view images. Viewed images always appear as a chip on the tool step that produced them — click the chip to open the image, even when the model itself cannot see it.

A working specialist's identity mark glows and breathes; a finished one is still. That is state, not decoration, so it survives a reduced-motion preference — the pulse stops, the glow stays. If a mark's artwork cannot be loaded it falls back to its own coloured shape rather than a broken-image placeholder.

The list keeps the order agents were first seen in. A new specialist joins at the end and never pushes the others around, so a row you are reading does not move under you as the backend reports.

A diamond (◆) means an agent needs you; a filled dot (●) means work is queued or running. The editor uses an empty ring (○) when the turn still has agents but none is working any more. Reopening a chat restores spawn cards and identity chips next to the task that started them. Compaction summarises those turns for the model, but the chips stay in the human log after the summary marker — they are not dumped under the last answer. Clicking a chip opens that agent's page: its report, files, and any tool steps DGC kept for the person. Rewinding drops agents started later.

In the terminal

#

The status bar shows active work after the shortcut hints:

● 2 agents        ◆ 2 agents · 1 needs you

Under 80 columns it shortens to ●2 or ◆2. With no active agents, the shortcut bar hides the count.

/agents lists the agents in this chat above the sub-agent settings, and works while a turn is running. Each row has the agent's state, its task description, and what DGC knows about it: what it is doing now, the agent type, the model when it is not the chat's own, how long it ran, its tool calls and its tokens. An agent started by another agent is indented under it. The /dashboard entry of a busy chat says how many of its agents are working. The classic dgc prompt prints the same list without colour.

In a long chat the list starts with what matters now: every agent working, the agents your latest turn that started any started (a short follow-up that starts none leaves them listed), and any older agent whose changes were held back, with the agents that started them. The rest is one line, ⋮ Earlier · 14 agents · /agents all lists them; /agents all lists every one. A chat saved before DGC kept the time of each prompt lists every agent, as before.

In the editor

#

A pill at the start of the controls under the prompt shows ● 2 agents (only the number in a narrow panel). Hover it to read how many are working. Click it for the list:

  • a summary such as 2 agents · 2 working;
  • one row per visible agent with the same facts the terminal shows, updated as it works;
  • click a row or a coloured chip in the transcript to open that agent's page;
  • Sub-agent settings opens Settings ▸ Agents, where the sub-agent model and host are chosen.

The list is for looking. Stop ends the whole turn, including every agent. When the chat is reopened, saved tool steps retain earlier results without repopulating the prompt area with completed work. If DGC's backend stops, the agents that were still running are marked stopped.

The agent map opens on what matters now: every agent working, the agents your latest turn that started any started, and any older agent whose changes were held back (its row says Held back), each with the agents that started it. Its subtitle counts them, such as 2 working · 3 this turn · 14 earlier. Everything else is one row at the end, Earlier in this chat · 14 agents: open it for the rest, grouped under the prompt that started them, newest first, and click any of them for its card as usual. Whether it is open is remembered for each chat. A chat whose agents don't say which turn started them lists every agent, as before.

Limits

#
  • The list shows up to 64 agents, the working ones first; the count stays exact beyond that.
  • Descriptions and failure messages are redacted the same way the transcript is. A row shows the first line of a failure message.
Documentation