> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chronicle-labs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Go

> Install the Chronicle Go SDK and run your first evaluation.

## Install

```go theme={null}
// go get github.com/chronicle-labs/chronicle-go
import chronicle "github.com/chronicle-labs/chronicle-go"

client := chronicle.NewClient() // reads CHRONICLE_API_KEY and CHRONICLE_API_URL
// or: chronicle.NewClient(chronicle.WithAPIKey("chr_..."), chronicle.WithBaseURL("https://api.your-chronicle-deployment.com"))
```

Go 1.22 or later. Every method takes a `context.Context` first and returns
`(value, error)`. Use one client for the life of your program.

## Run an evaluation

Before running this example, [register `billing-agent@1.0.0` and configure its
run command](/platform/agents). Set `CHRONICLE_API_KEY` and `CHRONICLE_API_URL`
using [Authentication](/api-reference/authentication). The script selects the
built-in world by its `triage-duplicate-invoice` task key; it stops if that
example is unavailable.

The keys `demo-1` and `demo-run-1` identify this first attempt. Keep them when
retrying the same inputs; change them when you want a new world or evaluation.
If task setup is not ready, keep the returned world ID and follow
[task setup recovery](/api-reference/worldsmith#retry-task-setup).

```go theme={null}
package main

import (
    "context"
    "fmt"
    "log"
    "time"

    chronicle "github.com/chronicle-labs/chronicle-go"
)

func main() {
    if err := evaluate(); err != nil {
        log.Fatal(err)
    }
}

func evaluate() error {
    ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)
    defer cancel()
    client := chronicle.NewClient()
    examples, err := client.Worlds.Examples.List(ctx)
    if err != nil { return err }
    var blueprint chronicle.WorldBlueprint
    found := false
    for _, example := range examples.Items {
        for _, task := range example.Blueprint.Scenario.Tasks {
            if task.Key == "triage-duplicate-invoice" {
                blueprint, found = example.Blueprint, true
                break
            }
        }
        if found { break }
    }
    if !found { return fmt.Errorf("the duplicate-invoice example is not available") }
    preview, err := client.Worlds.Compile(ctx, chronicle.WorldCompileParams{Blueprint: blueprint})
    if err != nil { return err }
    if len(preview.Problems) > 0 { return fmt.Errorf("blueprint: %v", preview.Problems) }

    world, err := client.Worlds.Create(ctx, chronicle.WorldCreateParams{
        Blueprint: blueprint, IdempotencyKey: "demo-1",
    })
    if err != nil { return err }
    world, err = client.Worlds.Wait(ctx, world.World.ID)
    if err != nil { return err }
    if world.Status != "ready" {
        return fmt.Errorf("world %s: %s; %v", world.World.ID, world.Status, world.LaunchError)
    }
    if world.Evaluation == nil || world.Evaluation.Status != "ready" {
        return fmt.Errorf("task setup is not ready for world %s; see the Worlds guide", world.World.ID)
    }

    run, err := client.Evaluations.Create(ctx, chronicle.EvaluationCreateParams{
        TaskSuiteID: world.Evaluation.TaskSuiteID,
        Agents: []string{"billing-agent@1.0.0"}, IdempotencyKey: "demo-run-1",
    })
    if err != nil { return err }
    run, err = client.Evaluations.Wait(ctx, run.ID)
    if err != nil { return err }
    if run.Status != "succeeded" { return fmt.Errorf("evaluation %s: %s; inspect its trials", run.ID, run.Status) }
    results, err := client.Evaluations.Results(ctx, run.ID)
    if err != nil { return err }
    for _, task := range results.TaskResults {
        fmt.Println(task.TaskID, task.Passed, task.FailedScorers)
    }
    return nil
}
```

In the dashboard, evaluations are under **Backtests**.
[Inspect the example task](/product-explorer#agent-task) and compare it with
the [trial scores](/api-reference/evaluations#inspect-trials).

To see individual scores, add this inside `evaluate`, before `return nil`.
It reads every page:

```go theme={null}
page, err := client.Evaluations.Trials.List(ctx, run.ID, chronicle.PageParams{Limit: 100})
if err != nil {
    return err
}
for {
    for _, trial := range page.Items {
        fmt.Println(trial.ID, trial.Agent, trial.TaskID, trial.Status)
        for _, score := range trial.Scores { fmt.Println(score.Name, score.Score, score.Passed) }
    }
    if !page.HasNextPage() { break }
    page, err = page.GetNextPage(ctx)
    if err != nil { return err }
}
```

## Errors and configuration

As an alternative inside `evaluate`, replace the client initialization with
the options below. Add `"errors"` to the program's imports for `errors.As`.

```go theme={null}
client := chronicle.NewClient(
    chronicle.WithTimeout(30*time.Second),
    chronicle.WithMaxRetries(2),
)

world, err := client.Worlds.Retrieve(ctx, "<world-id>")
if err != nil {
    var apiErr *chronicle.APIError
    if errors.As(err, &apiErr) {
        fmt.Println(apiErr.StatusCode, apiErr.Message, apiErr.RequestID)
    }
    return err
}
fmt.Println(world.World.ID)
```

`Wait` methods respect the context deadline, and the deadline only stops
waiting; the run continues on the server. Pages have `Items`, `HasNextPage()`,
and `GetNextPage(ctx)`. Optional numeric fields (`TTLHours`, `Limit`) use zero
for "not set". See [Errors and retries](/api-reference/reliability).
