---
title: Multi-turn evals
description: >-
  Send follow-up turns in one agent session, and check each turn's status, diff
  and transcript.
---
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reeval.ai/llms.txt
> Use this file to discover all available pages before exploring further.

Real work takes more than one prompt. Call `c.send` again and the agent carries on in the same session, with the same workspace. This is the second `greet` eval:

```ts title="evals/hello.eval.ts"
evaluate('adds a default name in a follow-up turn', async (c) => {
  await c.send(
    'Create greet.js exporting greet(name) that returns "Hello, <name>!". ' +
      'No dependencies.',
  )
  await c.send(
    'Make name default to "world" ' +
      'when greet() is called without arguments.',
  )

  await expect(c.exec(callGreetWithNoArgs)).toSucceed()
  expect(
    await c.judge(
      'Did the agent add the default without breaking greet(name)?',
    ),
  ).toPass()
})
```

The checks run after both turns, and the judge grades the latest one.

## Run it

```bash
npx reeval run hello --log-order grouped --output-logs full
```

```text
…
[adds#1 cursor] ▶ evals/hello.eval.ts › greet module › adds a default name in a follow-up turn
[adds#1 cursor]  +0:00 sandbox ready 2s
[adds#1 cursor]  +0:01 turn 1 done 8s · 3 tool calls, 1 file edit
[adds#1 cursor]  +0:10 turn 2 done 4s · 1 tool call, 1 file edit
[adds#1 cursor]  +0:14 $ node -e "import('./greet.js').then((m) => {…  exit 0 103ms
[adds#1 cursor]  +0:14 judge  pass 1.00 (≥ 0.8)  Did the agent add the default without breaking greet(name)?

pass             greet module › creates a tested greet module
pass             greet module › adds a default name in a follow-up turn
…
```

Each turn gets a line with its time, tool calls and file edits. The record and the studio keep each turn.

## Keep each turn

```ts title="evals/guide.eval.ts"
evaluate('checks turns', async (c) => {
  const first = await c.send(
    'Create greet.js exporting greet(name) that returns "Hello, <name>!".',
  )
  const second = await c.send('Make name default to "world".')
  // …
  expect(c.turns).toHaveLength(2)
})
```

`c.send` returns a `Turn` for that turn, and `c.turns` lists every turn so far, oldest first. A turn doesn't change after it resolves, so you can check the first one after the second has run.

## Check a turn's status

```ts
expect(second.status).toBe('completed')
```

`status` is `completed`, `aborted` or `error`. A turn that errors doesn't throw, so check the status when the rest of the eval depends on the agent finishing.

## Check what changed

```ts
const changed = second.diff.files.map((file) => file.path)
expect(changed).toContain('greet.js')
expect(changed).not.toContain('package-lock.json')
```

`turn.diff` is every change since the eval started, as of the end of that turn: `files` (each with `added`, `modified` or `deleted`) and the unified `patch`. Files the environment wrote before the agent started aren't in it, so the diff is only the agent's work.

## Read the transcript

```ts
const edits = second.transcript.filter((e) => e.type === 'file-edit')
expect(edits.length).toBeGreaterThan(0)
```

`turn.transcript` is that turn's events, in order: `prompt`, `reasoning`, `text`,
`tool`, `file-edit`, `web-search`, `web-fetch`, `error` and `turn-end`. Use
`expect(turn).toHaveCalledSkill`, `toHaveCalledMcp`, `toHaveCalledTool`,
`toHaveRun`, `toHaveEdited`, `toHaveSearched` and `toHaveFetched` for the
events reeval already normalises, or filter the array yourself.
[Matchers](/reference/matchers#transcript-matchers) and
[Transcripts](/reference/transcript) list every field.

## Judge an earlier turn

```ts
const created = await c.judge('Does greet.js export greet(name)?', {
  on: first,
})
expect(created).toPass()
```

`c.judge` grades the latest turn unless you pass `on`. `on: turn` grades an earlier turn, and `on: value` grades any value, such as a command's output.

<Info>
  Checks and `c.exec` see the workspace as it is now, after every turn. To check the state between turns, run the check before the next `c.send`.
</Info>

## Next

<CardGroup cols={2}>
  <Card title="Compare and lift" icon="chart-line" href="/guide/compare">
    Run with and without a skill and read the lift.
  </Card>
  <Card title="The attempt context" icon="book" href="/reference/attempt-context">
    The `Turn` shape and every `c` method.
  </Card>
</CardGroup>
