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

# build

> Compile firmware as a Chiplab job on your project, then read the result and download the artifacts.

<Info>
  This page describes what your AI agent can do with Chiplab.
  You don't need to call anything yourself, just ask your agent to build your firmware and it takes care of the rest.
  This is a reference for the curious, not a set of instructions for you to follow.
</Info>

A build is a job on your [project](/tools/run#projects).
Chiplab keeps it next to your runs, so a compile from an earlier session is still there the next time your agent connects.

Your agent discovers the call that starts a build from the tools available when it connects.
Reading the result is the same for every build.

## Listing builds

`list_jobs` returns the project's jobs, most recently started first.

<ParamField body="project_id" type="string" required>
  The project whose builds you want.
</ParamField>

<ParamField body="kind" type="string">
  Pass `build` to list builds only. Omit it to list runs and builds together.
</ParamField>

<ParamField body="created_before" type="string">
  An RFC 3339 timestamp. Only jobs started before this time are returned. When `more_available` is true, pass the `created_at` of the last job in the page to continue.
</ParamField>

<ResponseField name="job_id" type="string">
  Identifier for this build. Pass it to `wait_for_job` to read the result.
</ResponseField>

<ResponseField name="status" type="string">
  Where the build is in its lifecycle.
</ResponseField>

<ResponseField name="created_at" type="string">
  When the build started.
</ResponseField>

The listing carries the job's identity, status, and time.
Pass `job_id` to `wait_for_job` for what the build produced.

```json theme={null}
{
  "project_id": "project_01...",
  "kind": "build"
}
```

## Reading the result

`wait_for_job` blocks until the build finishes or the timeout elapses.

<ParamField body="job_id" type="string" required>
  The `job_id` from `list_jobs`, or the id returned when the build was started.
</ParamField>

<ParamField body="timeout" type="number">
  How many seconds to wait. The server caps this value.
</ParamField>

<ResponseField name="status" type="string">
  `running`, `succeeded`, or `failed`.
</ResponseField>

<ResponseField name="input" type="object">
  What the build was started with, so a build from an earlier session can be recognized on its own.
</ResponseField>

<ResponseField name="result" type="object">
  Present when `status` is `succeeded`. Includes an `artifacts` list naming the files the build produced.
</ResponseField>

<ResponseField name="error" type="string">
  Present when `status` is `failed`. What went wrong.
</ResponseField>

A response with `status: "running"` and `timed_out: true` means the build is still going.
Calling `wait_for_job` again on a finished build returns the same response immediately.

## Downloading artifacts

`issue_download_ticket` takes the `job_id` and an `artifact_name` from the result's `artifacts` list.
It returns a presigned `download_url`.
A `GET` of that URL returns the artifact bytes, with no auth header.

A succeeded build's artifacts are what a later [run](/tools/run) can execute, once your agent has an `artifact_id` for that project.
