Skip to content

Squads and assignments

A squad works in a project: a repository (an https address), the branch runs start from (dev by default), the forge whose token pushes there, and the engine and account its runs use. In the app, Projects → New project adds one (name as a folder, personal/site; repository; forge) and the project’s Settings change its base branch, protected branches, engine and accounts, data rule, delegation and rules. From Claude or ChatGPT, kedalio.project_set does the same, with its data class (Engines and costs); kedalio.projects shows them.

The forge’s token goes to the vault, never through a chat. Forgejo, Gitea, GitLab and GitHub are supported for pushing, each a base address and a token; the Git tab reads Forgejo, Gitea and GitHub.

In the app: System → Keys and tokens → New forge. Write the name, the kind, its address and the token. On Forgejo and Gitea the token needs the scopes write:repository (read the code, push, open and merge pull requests) and write:issue (comment on and review pull requests; without it comments are refused), and read:user, which is optional: without it the repository list in New project uses the forge’s own search. When the forge refuses for a missing scope, Kedalio names it: add it on the forge and save the token again, then choose the forge in the project’s Settings. Write the same name again to replace the token.

  • From the app: Projects → the project → New squad. Write what it should do (goal, context, what «done» means), choose the project, the host («Any host online» by default) and the budget in dollars (10 by default), then «Start the squad».
  • From your agent: it proposes a brief; approving it starts the squad (Your agent).
  • From Claude or ChatGPT: work.start with the project and the brief.

The first agent is the squad’s leader. Each agent works in its own worktree, on its own branch kedalio/<run-id>, which the host pushes every two minutes when it moves and once more at the end.

Agents start agents with the same tools, limited to their own subtree. The whole tree shares one budget, enforced by the server:

Limit Default for a squad
Depth 3 levels
Agents at work at once 4
Agents in all 20
Cost $10
Deadline 24 hours (at most 30 days)

A child gets what is left of its parent’s budget: one level less, and by default a share of the cost and only itself. When the cost or the deadline is reached, the server stops that subtree and tells you. Costs are counted in dollars from the ledger.

Each agent has a delegation: tool rules in Claude Code’s permission syntax (allow, ask, deny), for example Bash(pnpm test:*). What a run may do is what every grant from the root down to it allows. The most restrictive answer wins, and anything not matched is a request.

A request goes first to the nearest parent at work, which answers within its own delegation: it can never allow more than it may do itself. If the parent does not answer within five minutes, or the action is beyond it, the request climbs, up to you.

Some requests always reach you, and are serious: you confirm them with your passkey. They are a push to a protected branch, a push with --all, --mirror or --tags, turning a sandbox off, reaching the host’s token or another run’s files, and whatever matches a «serious» rule of yours.

In the app, a request shows who asks and where, the exact command, and why it reached you, with Allow (or Allow with passkey), For the whole session and Deny. You get it as a notification too.

Codex never asks: it runs in its own sandbox without network and without approvals, so a Codex agent makes no requests.

A project’s Squads tab, and the squad’s own page, show the squads at work and the finished ones as live trees: for each agent its state, engine, model, account, host and cost, and the budget used at the top. Stop this branch stops an agent and everything under it; their work so far stays on their branches. Today shows what is waiting for you first, then what is at work.

An assignment is work with a «when». You make it in the app (a project’s Assignments tab, or Assignments → New), or say it in Claude or ChatGPT with the connector («every weekday at 8, check the production health of project A»): the client reads it back to you and adds it (tasks.assignment_add) once you agree; tasks.assignment_list shows them. In the app they are three groups (on a habit, once, on an event) and an ended one keeps its history. Each assignment has:

  • what: a brief, a project, optionally the engine account and the host;
  • when: a schedule (five-field cron on your time zone), a date (2026-11-03T09:00, 09:00 for the next one, or +2h), or an event;
  • what it produces, in words;
  • whom it tells: a notification, a line in the diary, the morning report (the report reads every firing anyway).

The events are: an issue labelled on the project’s repository (Kedalio adds the webhook itself on Forgejo and Gitea; on other forges you add it by hand), a webhook of your own at /hooks/… with an optional HMAC signature (its address is shown once, when you create it), and another assignment’s run ending. Run now fires one at once.

A firing that cannot start waits for a host for its grace time (60 minutes by default), then counts as missed. An assignment is paused, resumed or ended, which is for good; in the app you can also delete it with its history of firings, and the runs it started stay.

Agents in a squad can schedule themselves too, for a follow-up in their project: a date only, at most 30 days away, with what is left of their budget and delegation, and at most five a day per squad by default.

Your time zone is set in System → Preferences (Accounts and access): «Assignments and the morning report follow this clock.»

What happens when an assignment fires at night, and the morning report, are in Unattended runs.

Not built yet: triggers from mail and calendar, the trail of who answered a request, and turning a repeated answer into a rule with one tap.