NewPer-task model routing and cost caps→

Describe the change. Get the pull request.

Handyst reads your repository, plans the work, edits the code, runs your tests in an isolated sandbox and opens a pull request for your team to review. Every command is sandboxed and logged, and it works with the model you choose.

First PR on day oneA sandbox per sessionAny leading modelNothing merges without review
handyst · acme/api-gateway · session 7f3aQueued
Terminal/workspace/api-gateway
No changes yet

Reading the code before changing it.

runtime healthybranch handyst/rate-limit-uploadelapsed 00:00

This session is live. Click a changed file to read its diff, type in the chat to steer the agent, or pause the run.

Plugs into where your code and conversations already live, and works in any language in the repo

GitHub & GitHub EnterpriseGitLabBitbucketSlackCLIHeadless mode for CIREST APIWebhooksAny OpenAI-compatible modelClaude, GPT & GeminiOIDC & SAML sign-in
TypeScriptPythonGoRustJavaKotlinRubyPHPC#SwiftElixirC++TerraformSQL

The problem

Every team has a backlog of changes nobody has the afternoon for.

Everyone knows how to fix them. They're just never urgent enough to beat the roadmap. So they age, and the codebase pays interest.

  • Hand off the well-described work. Bugs with a repro, upgrades, tests, docs, CI fixes.
  • Keep the judgement. Every change comes back as a pull request your team reviews.
  • Keep the receipts. Every command, edit and network attempt lands in an audit log you can search and export.
acme / issueslabel:chore · oldest first
#1204Upload returns 500 when the file is empty31 daysPR opened
#1188Flaky: invoice due-date test fails on CI74 daysPR opened
#1162Bump axios, drop the old retry shim118 daysPR opened
#1140Add /health endpoint for the load balancer142 daysPR opened
#1097Document deployctl rollout flags203 days
#1043Migrate date-fns v2 → v3260 days
#998Replace deprecated Buffer() calls311 days
7 open · oldest 311 days4 handed to Handyst this morning

Pick a task

Four chores. Four pull requests.

Choose a task and watch a replay of how the agent handles it: it reproduces, reads, edits, runs and checks its own work before it hands anything back.

Scripted replays of real-shaped runs. Timings and diffs are illustrative.

acme/billing · handyst/fix-flaky-due-daterunning

test/invoice.test.ts fails on CI a few times a week. Find out why and fix it.

0 / 10 steps

The agent loop

Think, act, observe. Then do it again.

The agent never guesses a whole change in one shot. Each step it picks one tool, runs it, reads the result and decides what's next. Nudge it toward a tool and see the loop adapt.

Nudge the next action
event streamsession 7f3a · 1 event per step
#038thinkWhere is the upload route defined?
#039actionsearch("api/upload", "src/")
#040observe2 matches · src/routes/upload.ts:7
Every step is an event. The same stream drives the UI, the audit log and replays.

What it can do

A junior engineer's hands. A senior engineer's checks.

Handyst works the way you would: read first, change what's needed, run it, and hand it over in a form your team already knows how to judge.

Reads the repository

Works from the code as it actually is, not from a description of it. It searches, follows imports and reads the tests before it writes a line.

src/

app.ts

routes/

upload.ts

middleware/

auth.ts

lib/

redis.ts

test/

upload.test.ts

helpers.ts

0lines read
0files opened
0call sites found

Writes and edits

Makes the change across the files it touches, not one snippet at a time.

rateLimit.ts+19 −0
upload.ts+2 −1
rateLimit.test.ts+19 −0

Runs commands

Executes builds, tests, and tooling in a sandbox, then reacts to the output.

npm ci

added 214 packages in 8s

npm test

✕ resets the window after 60s

npm test

✓ 148 passed

Opens pull requests

Hands work back the way your team already reviews it.

#482 Rate limit POST /api/uploadhandyst-bot · 3 files · +40 −1linttypecheckunit · 148build image

Isolated runtime

Every session runs in its own container, so an agent cannot reach past its task.

Human review

Nothing merges on its own. Every change waits for an engineer to approve it. The agent can respond to comments, but merge rights stay with people.

review gate · #482Branchpushed by agentCI6 checks passedComments1 follow-upReviewer@acme/apiProtection1 approval req.Mergeby a person

The right model for each job

Use a frontier model for hard, multi-file changes and a fast, low-cost one for chores. Switch per team or per task.

anthropic/claude-sonnet-4hard changesgemini/gemini-2.5-prohuge reposopenai/gpt-4.1everyday workmistral/devstral-mediumhigh volumeopenai/gpt-4.1-minidocs & chores

From sentence to pull request

Five steps, one reviewable change.

The same shape every time, whether the task is a one-line fix or a thirty-file upgrade.

01

Describe

Write the change the way you'd brief a colleague: what, where, and how you'll know it works. From an issue, a Slack thread, the CLI or the web app.

New sessionacme/api-gateway

Add rate limiting to POST /api/upload: 10 requests a minute per API key. Return 429 with Retry-After. Include tests.
repo · api-gatewaybase · mainmodel · claude-sonnet-4reviewers · @acme/api
Start session ↵
02

Explore

The agent searches the repository, opens the files that matter and reads the tests. It builds its plan from the code as it is, not from a guess.

Explorerg · read_file

src/routes/upload.ts:7 uploadRouter.post("/api/upload", auth, …)

src/middleware/auth.ts:22 req.apiKey = await lookupKey(token)

src/lib/redis.ts:4 export const redis = new Redis(env.REDIS_URL)

test/upload.test.ts:9 upload("key_a").expect(200)

14files read
2,310lines
5plan steps
03

Change

It edits across every file the change touches, in your conventions, on its own branch. Formatting and imports come along.

Changehandyst/rate-limit-upload

ArateLimit.tsMupload.tsArateLimit.test.ts

src/routes/upload.ts

2import { auth } from "../middleware/auth";
3+import { rateLimit } from "../middleware/rateLimit";
−uploadRouter.post("/api/upload", auth, handleUpload);
7+uploadRouter.post("/api/upload", auth, rateLimit, handleUpload);
04

Verify

It runs your builds, linters and tests inside the sandbox. When something fails it reads the output, fixes the cause and runs them again.

Verifysandbox ws-7f3a

run 1 · rateLimit.test.ts3/4
run 2 · rateLimit.test.ts4/4
full suite · 25 files148/148
eslint · tsc --noEmitclean

✓ Fixed its own failing test before anyone saw it

05

Review

You get a pull request with a summary, how it was verified and what deserves a second look. Comment on it and the agent pushes a follow-up.

Reviewgithub.com

#482 Rate limit POST /api/upload per API key+40 −1 · 3 files · 6 checks passed

Summary · How I verified it · Worth a look

MRMarco R. requested one change. Handyst pushed 3f9c2e1.

✓ Approved by a person. Merged by a person.

Sandbox isolation

Let it run anything. Let it reach almost nothing.

Every session gets its own container with a copy of the repo, hard resource limits and an egress allowlist you control. Try to break out. Then change the policy.

container · session 7f3anode:22 · rootfs read-only
agent runtime/workspace · copy of acme/api-gateway
cpu1.4 / 2 vCPU
mem2.0 / 4 GB
  • registry.npmjs.orgPackage registry
  • pypi.orgPython packages
  • git.acme.devYour git host
  • 169.254.169.254Cloud metadata
  • pastebin.comPaste sites
  • evil.exampleUnknown hosts

Try to break out

* everything else deny

curl 169.254.169.254/latest/meta-data/iam/169.254.169.254blocked by egress policy
npm ciregistry.npmjs.orgallowed · 214 packages

Review the PR

It hands you a pull request. You stay the reviewer.

A clear summary, a real diff, your CI checks and a thread you can reply to. Request a change and watch the agent push a follow-up commit.

github.com/acme/api-gateway/pull/482checks running

Rate limit POST /api/upload per API key #482

Openhandyst-bot wants to merge 1 commit into main from handyst/rate-limit-upload

handyst-botopened this pull request from session 7f3a

Summary

  • Adds a sliding-window limit of 10 uploads per minute per API key to POST /api/upload.
  • Returns 429 with Retry-After: 60. Other routes are untouched.
  • Counts live in a Redis sorted set that expires with the window.

How I verified it

  • 4 new tests: the limit, the 429, the reset, per-key isolation. Full suite: 148 passing.

Worth a look

  • The first version read performance.now(), which the test clock doesn't move. It now uses Date.now().
src/middleware/rateLimit.ts+19 −0
4+const WINDOW_MS = 60_000;
5+const LIMIT = 10;

Marco R. reviewer

Staging runs load tests at about 50 uploads a minute. Can this be configurable?

handyst-bot agent

It can. Request changes with the variable name you want and I'll push a commit.

6+
7+export async function rateLimit(req: Request, res: Response, next: NextFunction) {

Start a session anywhere

Mention it in an issue. Or in Slack. Or in CI.

Handyst meets your team where the work is described, then reports back in the same place.

acme/api-gateway · Issue #1204

OpenUpload returns 500 when the file is empty

sam-l commented

Repro: curl -F file=@/dev/null …/api/upload gives a 500 instead of a 400.

priya-k commented

@handyst fix this and add a test.

handyst-bot commented

On it in session 9c1e. Reproduced the 500 in the sandbox.

Opened #1207 Return 400 for empty uploads · +18 −2

  • Mention @handyst in an issue or PR comment
  • Or add the handyst label to queue it
  • Ask it to address review comments on its own PRs
  • GitHub.com or GitHub Enterprise Server

Choose your model

The model that fits the job.

Hard refactors deserve the strongest model. Docs and chores don't. Pick a model and a job to see the trade-off between quality, speed and cost.

The job
Quality92/100 on multi-step coding tasks
Speeddeliberate
Cost$6.00 per million tokens
est. time~11 min
est. model cost$3.6
6 files · 0.6M tokensgood fit for this job
handyst.tomlillustrative
# Default model for this team
[llm]
model = "anthropic/claude-sonnet-4"
temperature = 0.0

# Optional: send small jobs to a cheaper, faster model
[llm.routing]
bug = "openai/gpt-4.1-mini"
max_cost_per_task = 8.00

The strongest planner for multi-file changes and upgrades. Fewer review rounds on hard tasks.

The difference

Autocomplete in the editor
versus an agent that ships.

Inline suggestions save keystrokes. The backlog still needs someone to reproduce, change, test and open the pull request.

Chat and autocomplete assistantsHandyst
Unit of workA suggestion in one fileA finished change across the repo
VerificationYou run the tests yourselfRuns builds and tests, fixes its own failures
Where it hands offA snippet to copy and pasteA pull request with a summary and a diff
Who drivesAn engineer at the keyboard, all the wayBrief it once, review the result
Starting a taskOnly from inside the editorIssues, Slack, CLI, CI or the web app
The modelWhichever one the tool ships withPick per team or per task by quality, speed and cost
Audit trailA chat history, if you kept itEvery command, edit and network attempt logged

Control and security

An agent with a shell, on a very short leash.

Security teams ask the same questions every time. Here are the answers, and the log that proves them.

audit.log · session 7f3astreamed to your SIEM · append-only
timesessionactoractionresulthash
10:42:077f3apriya.ksession.startapi-gatewaya41f09
10:42:117f3aagentrun git checkout -b handyst/rate-limit-uploadexit 0c02b7e
10:42:407f3aagentedit src/middleware/rateLimit.ts+199d11a3
10:43:027f3aagentnet curl 169.254.169.254/latest/meta-datadeniede7a0c4
10:43:187f3aagentrun npm test148 passed51fe2d
10:43:317f3aagentgit push origin handyst/rate-limit-uploadscoped token7bc3e0
10:43:337f3aagentpr open #482review req.0d9e6b

A sandbox per session

A fresh container with a copy of the repo, a read-only root filesystem and no host mounts. Thrown away when the session ends.

Secrets stay secret

Short-lived git tokens scoped to one repository. Other secrets are encrypted at rest, injected only where needed and masked in every log.

Every command audited

Each command, edit, network attempt and git operation is recorded with the session and the person who started it, then kept append-only and exportable to your SIEM.

Humans approve merges

The agent pushes branches and opens pull requests. Your branch protection and reviewers decide what reaches main.

Egress you define

Allowlist your registries and git host. Everything else, including cloud metadata endpoints, is denied and logged.

SSO and roles

Sign in with OIDC or SAML. Roles decide who can start sessions, on which repositories, with which models and budgets.

FAQ

Questions, answered.

If it isn't here, write to us and an engineer who runs Handyst will answer.

How long does it take to get started?

Most teams open their first pull request on day one. Connect your git host, pick a repository and a model, and describe a task. We help you tune sandbox policies and review settings during onboarding, and an engineer from Techyst stays on hand while your team finds its rhythm.

Can the agent merge its own pull requests?

No. It pushes to its own branch and opens a pull request. Your branch protection decides what merges, and that means a person approving it. The agent can respond to review comments with follow-up commits, but it never gets merge rights.

Which models can we use?

Any leading coding model, including Claude, GPT, Gemini and Devstral, plus any OpenAI-compatible endpoint. Stronger models do better on larger, multi-file changes; faster, cheaper ones are ideal for docs and chores. Set a default per team and route small jobs to a lighter model to keep costs down. We'll help you pick for the work you actually do.

What can the agent reach from its sandbox?

Only what your policy allows. By default that means package registries and your git host. Cloud metadata endpoints, host credentials and the open internet are blocked, and every attempt is logged. CPU, memory, process count and session time are capped per session.

How are secrets handled?

Git access uses a short-lived token scoped to the repository in the task. Other secrets come from your secret store, are injected only into sessions that need them and are masked in transcripts and logs. Nothing is baked into prompts.

What kind of work is it good at?

Well-described changes with a way to check them: bug fixes with a repro, tests, small features, dependency upgrades, migrations, docs and CI fixes. It's less suited to open-ended design decisions, which is why every change arrives as a pull request for review.

Does it have an API?

Yes. Everything in the web app is available over a REST API and the handyst CLI: start sessions, stream progress, fetch transcripts and read the audit log. Headless mode returns JSON and exit codes, so it slots into scripts and CI.

How does pricing work?

Pricing isn't per seat, so it doesn't grow every time another engineer starts using it. Model usage is billed at your provider's rates, with per-task cost caps you control. Ask us for a quote.

Stop babysitting small changes. Review them instead.

Point Handyst at a repository, describe a change you've been putting off, and read the pull request over coffee.

$handyst run "the change you keep postponing"