Docs/Learned code (research preview)
Concepts

Learned code (research preview)

Turn what Sai did into Simulang code you own, run it without the agent, and repair it when it breaks.

View as Markdown

Sai solves a task by looking at the screen and deciding each step. Once it has solved a task, you can turn what it did into a Simulang function and run that function again with new inputs, without the agent. The code is faster and cheaper to run, and you can read it, test it and keep it under version control. When the code breaks, Sai repairs it from what went wrong.

The loop has four calls, and you run each one yourself:

  1. Record. Send the task to POST /message with options.recordTrajectory: true, ideally as a template with inputs, so the inputs are named:

    json
    {
      "message": "Open {{site}} and read the title of the top story",
      "options": { "inputs": { "site": "https://news.ycombinator.com" }, "recordTrajectory": true },
      "wait": false
    }
  2. Learn. POST /v1/agents/learn with the turn's id returns async function main(params = { site: "..." }), the template and the parameters. A clarification you sent during the task, or a follow-up turn, can be included by listing its turn too.

  3. Run. Open a control lease and run the code with new inputs: await main({ "site": "https://lobste.rs" }) as the block's last line. The block's result is what main returns. The code throws needs_sign_in: <site> when the computer is not signed in, and precondition_failed: ... when it starts on the wrong screen.

  4. Judge and repair. Check a run yourself, or with POST /v1/agents/judge. When it failed, call learn again with the code as initialCode and the run as an evaluation. If the code cannot handle a case at all, send the template to POST /message with those inputs, let Sai solve it, and pass that new turn to learn: the repair adds what the code was missing.

In the SDKs:

python
learned = sai.learn.create([turn])
with sai.control.open(machine=pc) as lease:
    r = lease.run(learned, {"site": "https://lobste.rs"})
    if not r.ok:
        learned = sai.learn.create(
            initial_code=learned.code,
            evaluations=[Evaluation(inputs={"site": "https://lobste.rs"}, result=r, passed=False)],
        )

What the code can do

Learned code runs in a control lease, so it can do what direct control can: the screen, apps, the browser, the shell, files, and callLLM to answer a question about the screen (billed to your account). It cannot ask a person anything mid-run. showMessageToUser writes a line to the run's logs.

Limits of the preview

  • learn reads the steps, the agent's reasoning, their results and the final answer, not the screenshots.
  • One experience per call: turns from one session. Several demonstrations of the same task come later.
  • One exec runs for at most 300 seconds. For a longer task the code is split into step functions you call in separate execs.
  • learn never runs the code; you do, so you see each step.
  • The default model is anthropic/claude-opus-5-5. A conversion takes about two minutes.