nextv2.0.0
Customize and automate

Schedule or webhook work

File a paused work item on a cron schedule or from a webhook, then check that it arrived.

Set up a trigger that files a paused work item for you, from a cron schedule or from a webhook, and check that the item arrived. The fields and the HTTP contract are in Inbound triggers.

Before you start

  • A repo connected with kraft repo connect.
  • A running Kraft server.

Schedule a work item

  1. Add a schedules: entry to $KRAFT_HOME/config/intake.yaml:
    config/intake.yaml
    schedules:
      - cron: "0 9 * * 1,2,3,4,5"  # 9:00 UTC on weekdays
        repo: /path/to/repo
        chain: default
        title: "Weekday dependency check"
        description: "Filed by the 09:00 UTC weekday schedule"
    
  2. Make the server read the file:
    kraft admin reload
    
    reloaded <N> template(s) and policy.yaml and intake.yaml
    

    A file Kraft refused to read is named on a refused: line below it, and the running one is kept.
    If you add the schedule in Settings › Auto-intake (Add schedule) instead of editing the file, you need no reload.

Kraft evaluates the schedule in UTC. The next matching minute files the item.

File a work item from a webhook

Post to /api/triggers from anything that can fire a webhook, such as CI or a script. The body takes title, repo, and optionally chain and description.

Call it from the same machine

While Kraft is bound to 127.0.0.1 (the default), a call from the same machine needs no login. Address Kraft as 127.0.0.1, localhost, or [::1]:

curl -s -X POST http://127.0.0.1:8765/api/triggers \
  -H 'Content-Type: application/json' \
  -d '{"title": "Dependency check", "repo": "/path/to/repo", "chain": "default"}'

Kraft answers 201 with the new work item as JSON, filed paused. Cut to the fields that matter, the body reads:

{"id": "<work-item-id>", "title": "Dependency check", "status": "paused", "...": "..."}

Call it from another machine

After a non-loopback bind, every call needs the trigger token from $KRAFT_HOME/run/trigger-token, including one from the same machine. Use the address you reach Kraft at, and see Remote access for how to bind:

curl -s -X POST https://<your-tunnel-hostname>/api/triggers \
  -H "Authorization: Bearer $(cat ~/.kraft/run/trigger-token)" \
  -H 'Content-Type: application/json' \
  -d '{"title": "Dependency check", "repo": "/path/to/repo"}'

The trigger token is accepted only by POST /api/triggers, so it is the one to store as a CI secret or give a webhook sender. Do not use run/mcp-token there: it is a full-admin credential. See Rotate the token for how to rotate either.

If you get 403 or 401

Your callWhat happens
From the same machine, Kraft bound to loopback, addressed as 127.0.0.1, localhost or [::1]It works with no credential.
Through a tunnel or reverse proxy, Kraft bound to loopback403 (unexpected Host), whatever the credential.
Kraft bound beyond loopback, with no trigger token401, even from the same machine.

For a webhook that arrives through a tunnel or reverse proxy, follow Put a proxy in front of Kraft. Who may call lists every cause of a 403.

Check it worked

  1. For a schedule, wait for the next matching UTC minute, or test it right away: set cron: "* * * * *", reload, and do the checks below. Then restore the real expression and reload again, or the schedule files an item every minute.
  2. List the paused items and look for the new one:
    kraft view list --status=paused
    
    ID              STATUS  GATE  NODE  TITLE
    <work-item-id>  paused  -     -     Weekday dependency check
    

    The item shows under Not started on the board, and its STATUS reads paused.
  3. Start it when you are ready: click its row on the board, then Start in the side panel, or run kraft item resume ID.

If nothing appears, check the server log for a skipped-trigger warning. It names the unconnected repo or the unknown chain.

Next steps

Copyright © 2026