The umpteenth time runs itself.

Describe a recurring job in plain language. An AI agent runs it in a fresh sandbox and learns until a script does the work for next to nothing.

How it works

Three steps to the optimal job.

A job starts as an agent exploring. It ends as a script, with the agent on call. Every run in between makes the next one cheaper.

  1. Explore

    1Describe it

    Write the job like you would brief a colleague. A compile step turns it into a schedule, success criteria, outputs and the MCP servers it needs, and you confirm before saving.

  2. Assisted

    2Run it in a sandbox

    Every run gets a fresh container with resource limits, no capabilities by default and a network policy. The agent works with shell tools and your MCP servers, and every step is recorded with its cost.

  3. Scripted

    3Let it learn

    After a run, reflection writes down what the job learned: notes, tested scripts, installs moved into its Dockerfile. Once three successful runs that do the work take the same steps, it can graduate to a script that runs without the agent.

A few use cases

A job starts from an alert, a release or a schedule. The agent collects what it needs from your tools and puts the result where you see it first.

Checkout alert triageSucceeded
Webhook{"alertname": "HighErrorRate", "service": "checkout"}
  1. loki__query_range{app="checkout"} |= "error"1,284 lines+3s
  2. bashgit log --since="3 hours ago" --oneline2 commits+9s
  3. read_filerunbooks/checkout.md86 lines+14s
  4. loki__query_range{app="checkout"} |= "too many connections"94% of errors+26s
  5. oncall__add_noteHighErrorRateadded+50s

Note on the alert

HighErrorRate · checkout

Errors started at 02:51, four minutes after the deploy of #1432, which lowered the database pool to 10.

94% of them are pq: too many connections. Rolling back #1432 or raising the pool size clears them.

Docs syncSucceeded
Webhook{"tag": "v2.4.0"}
  1. bashgit log v2.3.0..v2.4.0 --oneline41 commits+2s
  2. bashgrep -rln "SESSION_TTL" docs/2 pages+11s
  3. edit_filedocs/configuration.md+4 −3+34s
  4. edit_filedocs/upgrading.md+12+47s
  5. github__create_pull_requestacme/web#1455+1m 03s

Pull request

Update the docs for v2.4.0

acme/web #1455 · 2 files changed

docs/configuration.md

Set `SESSION_TTL` to the session length in hours.

Set `session.ttl` to a duration, such as `12h`.

Security report checkSucceeded
Schedule0 * * * *
  1. github__list_security_advisoriesstate=triage1 new report+2s
  2. read_filereport.md2,113 words+4s
  3. bashgit log -S parse_header_ex --onelineno commits+9s
  4. bashgcc poc.c -lparse -o pocundefined reference+17s
  5. slack__post_message#securitysent+38s

Posted to #security

Heap overflow in parse_header_ex()

Reported as critical · 2,113 words

Not reproduced

  • parse_header_ex() appears nowhere in the code or its history.
  • The proof of concept fails to build against any release.

Major upgradesSucceeded
Schedule0 2 * * *
  1. github__list_pull_requestsauthor:app/dependabotvite 5 → 6+2s
  2. bashpnpm test12 failed+41s
  3. bashcurl -s https://vite.dev/guide/migration48 KB+44s
  4. edit_filevite.config.ts+6 −2+1m 18s
  5. bashpnpm test214 passed+2m 07s
  6. bashgit push2 commits+2m 12s

Pushed to the pull request

Bump vite from 5.4.11 to 6.0.3

acme/web #412 · open since March

  • a41c9e2Switch Sass to the modern compiler API
  • 7be03fdSet resolve.conditions for the Vite 6 defaults

214 tests passed

Monday catch-upSucceeded
Schedule0 8 * * 1
  1. umpmcp call teams list_chats38 threads+1s
  2. umpmcp call outlook list_messages61 emails+2s
  3. umpmcp call github list_notifications24 notifications+3s
  4. umpllm --model utilitydigest+9s
  5. umpmcp call outlook send_mailsent+10s
  6. Verification passed3 of 3 checks+12s

Email to you

Your Monday catch-up

Waiting on you

  • TeamsPriya asked in #platform whether the Q3 migration can slip a week.
  • OutlookThe hosting contract needs your signature by Wednesday.
  • GitHubTwo review requests on acme/api, #881 and #884.

Decided while you were out

  • TeamsThe web team moved Thursday's release to Friday.

Named for the lazy developer's instinct. Do it by hand once and take notes. Script the boring parts the second time. Keep trimming until the job runs itself, and only get up when something breaks.

Umpteenth does the same on a schedule, with a receipt for every run, and it never forgets what it learned.

What you get

Everything a recurring job needs.

  • Plain-language jobs

    No workflow builder. You write what the job should do and Umpteenth figures out the rest. You check it before you save.

  • Triggers

    Run a job on a cron schedule with time zones, from a webhook, through the API or by hand with some input.

  • Isolated sandboxes

    Every run gets a fresh container. It runs as non-root with all capabilities dropped, and if you want you can put gVisor on top.

  • Egress control

    Sandboxes with internet go through a proxy, so they can't reach your private network, the Docker host or cloud metadata. You can also limit a job to some domains or turn off the network.

  • Per-job environments

    A job can have its own Dockerfile. The image gets built once and cached, so you don't install the same tools on every run.

  • MCP servers

    HTTP and stdio servers, and you pick which tools each job can use. Credentials of HTTP servers stay on the host, and stdio servers run as a different user than the agent.

  • Bring your own model

    Use the Anthropic API or anything that is OpenAI-compatible, like OpenAI, OpenRouter, Ollama, vLLM or LM Studio.

  • Cost control

    Set limits for cost, turns and time per run, plus a daily budget for the whole workspace. Every run shows what it cost.

  • Runs you can read

    Every run has a live timeline with all model calls, tool calls and outputs. Playbook changes are versioned, so you can diff and roll them back.

Give it the job you are tired of.

Describe it once. By the umpteenth time, it runs itself.