Field notes

Open-source AI chief of staff: six jobs and one send rule

An AI chief of staff is six recurring jobs on a schedule, and open-source Kortix keeps the jobs and the send rule in a repo everyone can read.

The Kortix Team
Kortix··7 min read

You bought the assistant. The Monday report still takes an hour, the standup still gets skipped the week it matters, and the investor update still starts from a blank document. A chief of staff owns a cadence, and the cadence runs whether or not anyone remembers it.

Kortix is the open-source CompanyOS. Everything the chief of staff runs on lives as files in the company's own repo, and the agents run them on cloud computers of their own. The chief-of-staff setup is six jobs with times attached, and one rule about what happens when a job tries to send something out of the building.

Six jobs with times attached

Ask a founder what their chief of staff does and you get a list of jobs with times attached. The weekly numbers. The standup. The notes from the call. The update to investors. The inbox. The quarterly review. Each one has a time it happens, an input it reads, and a place its output goes.

An executive assistant already runs a version of this list. The difference is that a person's list stops when they stop. A conversation in a chat window has the same problem: it starts when you start it, and a cadence starts on Monday at six whether or not you remembered.

Three of the six, in the words of the teams running them:

  • The weekly report. "A Monday cron queries the metrics from our Postgres database, writes the weekly report with commentary on what moved and why, and posts it to Slack. Access to the database is read-only."
  • The inbox. "It reads the email, applies a label, and then either drafts a reply in Gmail or files a task in Linear. Anything customer-facing waits for a person before it sends."
  • The meeting notes. "It writes structured notes, pulls out the action items, and files each one as a ticket assigned to the person who owns it."

The other three are in the trigger list, each with the prompt that defines it.

The list is also the test. If you cannot name the six jobs and the day each one lands, you have a chat window with a job title.

Six triggers in one file

kortix.yaml, the manifest that holds the project, carries every job in that list as a trigger. A trigger names the agent that runs, when it runs, and the prompt it starts with. The docs put the point plainly: a session can start from a schedule, from a webhook, or from an event in another app, with no one at the keyboard.

triggers:
  - slug: weekly-report
    type: cron
    agent: weekly-report
    cron: "0 0 6 * * 1"
    timezone: Europe/London
    prompt: "Query the metrics, write the weekly report with commentary, and post it to #metrics."

  - slug: standup-summary
    type: cron
    agent: standup-summary
    cron: "0 30 8 * * 1-5"
    timezone: Europe/London
    prompt: "Read each person's Linear issues and GitHub activity, write the standup, and post it to #standup."

  - slug: meeting-ended-check
    type: cron
    agent: meeting-notes
    cron: "0 */15 * * * *"
    timezone: Europe/London
    prompt: "Load the meeting-recap skill and write notes and tickets for every meeting that ended since the last check."

  - slug: investor-update
    type: cron
    agent: investor-update
    cron: "0 0 9 1 * *"
    timezone: Europe/London
    prompt: "Pull MRR, growth, burn, runway and active accounts, compare to last month and to plan, and draft the update."

  - slug: inbox-triage
    type: cron
    agent: inbox-triage
    cron: "0 */15 * * * *"
    timezone: Europe/London
    prompt: "Read new mail, label it, then draft a reply or file a Linear task. Leave anything customer-facing as a draft."

  - slug: qbr-prep
    type: cron
    agent: qbr-prep
    cron: "0 0 8 1 */3 *"
    timezone: Europe/London
    prompt: "Assemble the QBR deck in Slides and the briefing doc in Docs. Do not share, present or send anything."

All six are crons. Each run starts in a session of its own, on a machine spun up for it, so a slow Monday report never holds up the inbox sweep.

What happens when a job tries to send

Most of these jobs end inside the building. The report lands in a channel your team already reads. The notes become tickets. The QBR deck sits in Drive. Two of them leave: the inbox and the investor update. That is where the design question is.

A connector is what gives an agent the ability to send at all. Kortix covers 3,000+ apps in a click, plus MCP, OpenAPI, Postman, GraphQL and raw HTTP. Each connector carries its own policy, a list of match rules. Three actions are available: always_run, require_approval, block.

connectors:
  - slug: gmail
    policies:
      - match: send_*
        action: require_approval
      - match: reply_*
        action: require_approval
      - match: forward_*
        action: require_approval
      - match: delete_*
        action: block

require_approval holds the call until someone approves it. always_run lets it go. block means the call never runs, which is what you want on delete_*. The docs describe the Ask rule as holding the action until someone approves.

A grant is a separate question from a policy. An agent with no grant for the connector cannot call it at all, and the CLI prints none (default-deny) for that agent. So the real choice is four-way: no grant, allow, ask, or block.

Two things are worth knowing before you copy that block. Approval gates you set. Off until you set them. When no rule matches, a sensitive connector holds the call for approval, and otherwise policy.default_mode sets the outcome: allow_all, the default, runs the call, and risk lets a read through while writes and deletes wait. And the policy is not the only place the line sits: the agent's own instructions are the other. You want both, and both live in the repo.

That is also the answer to whether it can run unwatched. The schedule takes the person out of the start. The policy decides whether the person comes back at the send.

The failure mode is a correct email sent to the wrong person at the wrong hour, and the fix for that is a rule.

Why the file matters more than the model

The model is the part everyone argues about, and it changes every few months. The jobs and the rule about what may leave the building stay where you can read them.

Because the jobs and the rules are files, a change to them is a diff. An agent that edits the project files opens a change request, which a teammate merges. So when someone widens the inbox agent from drafts to sends, that edit shows up as one line in a review, next to the name of the person who approved it. A settings toggle moves and the behaviour changes, with nobody able to say who moved it. The diff shows what the agent will do next time.

The grant list is the other half. Each agent gets a connector only when someone grants it, and the grant sits beside the job it serves, in the repo. That is what makes the grant list the first thing to write, before the prompts. It is also why human in the loop and human on the loop stop being a philosophy here. They are a per-call setting in a file, and you can read which one applies before the job runs.

What the assistant-shaped tools leave out

Three products sell something close to this, and each is good at the part it chose.

alfred_ sells routines on credits, from $29.99 a month on annual billing, and a run of "plan my week" costs about 55 credits. The routine is theirs to define and it runs inside their product.

WorkBoard's AI Chief of Staff Agent is a set of workflows inside an OKR platform: draft OKRs from past outcomes, assess KR quality, find cross-org alignment. It fits if the OKR cycle is the cadence you are missing.

MyZone's Chief of Staff is a persona in the Ai1 platform, and it does state the boundary: "anything external or binding waits for your approval." What differs is where the rule lives. In Ai1 it is a platform setting. In Kortix it is one line in the file your team reviews.

All three are built for a person who wants the cadence handled inside someone else's app.

Where to start

Pick the two jobs that already have a fixed time in the week. For most teams that is the Monday report and the standup, because both already have a slot and both already get skipped.

Write the prompt the way you would brief a new hire: what to read, what to produce, and where it goes. Write the trigger, run it once by hand, and read the output before you let the schedule take over. Then set the policy on the one connector that can send, and put a cap on how often the trigger may start a session, because a job that runs every fifteen minutes with no ceiling is a bill nobody planned for.

The rest of the list can wait: two jobs that run every week beat six that run once and get switched off.

Run the cadence from a repo you own.

Free to start, free to self-host.

Get started

Own your company’s AI.Start today, in our cloud or yours.

Start for free

Open source · SOC 2 Type I · SAML SSO and SCIM · Any model, your keys