# Create coding

URL: https://docs.hanzo.ai/docs/openapi/agent/post-agent-coding

> Runs a coding task on a repository: clones it into a sandbox, lets a model read and edit the code, run the tests, and push the work to a branch.

`POST /v1/agent/coding`

> [Agent →](https://docs.hanzo.ai/docs/openapi/agent) · [All API references →](https://docs.hanzo.ai/docs/openapi) · [Get started →](https://docs.hanzo.ai/docs/guides)

|               |                                        |
| ------------- | -------------------------------------- |
| **Address**   | `https://api.hanzo.ai/v1/agent/coding` |
| **Method**    | `POST`                                 |
| **Operation** | `post_agent_coding`                    |
| **Auth**      | `Authorization: Bearer $HANZO_API_KEY` |

Runs a coding task on a repository: clones it into a sandbox, lets a model read
and edit the code, run the tests, and push the work to a branch. Say the thing
you want done — "fix the failing auth test in hanzoai/cloud" — and the run
infers the repo, the branch and the plan. No prefix, no ceremony.

Name no repo and the run works in an empty workspace of its own: nothing is
cloned and nothing is pushed, and what it makes is kept in its sandbox and as
its artifacts. Name a repository the caller can read and not push to — a public
one — and it is cloned read-only, the same way.

It answers 202 with the run's handle the moment the run is ADMITTED — not when
it finishes. A coding run takes minutes; holding a request open for one would
tie a connection to a model loop and give the caller nothing it cannot get
better from the session stream.

The handle is a session id, and that is deliberate: the session is already the
run's durable record and its live stream (/v1/agent/sessions/stream?root=\<id>), so
this op does not grow a progress endpoint, a status endpoint or a cancel
endpoint of its own. One way to watch a run, whoever started it.

It is also how work CONTINUES. Pass an earlier run's session as `after` and
this one starts from where that one stopped, so "now add tests for it" builds
on the branch already pushed instead of a fresh clone. The follow-up still gets
its own branch and its own session — one run, one branch, always reviewable on
its own.

## Request

21 fields, body `application/json` (required).

| Field            | In   | Type            | Required | Description                                                                                                                                                                                                                                                                                      |
| ---------------- | ---- | --------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `after`          | body | string          | —        | After names a previous run's session, and starts this one from where that one stopped instead of from the repository's default.                                                                                                                                                                  |
| `agentRef`       | body | string          | —        | AgentRef names a configured agent to run as, which is how an org pins a harness, a model and a prompt to a name.                                                                                                                                                                                 |
| `base`           | body | string          | —        | Base is the branch to start from.                                                                                                                                                                                                                                                                |
| `desktop`        | body | boolean         | —        | Desktop asks for a run with a SCREEN — an image carrying an X server — for a task that has to drive a browser or another windowed program.                                                                                                                                                       |
| `effort`         | body | string          | —        | Effort is how hard that model reasons: low, medium or high.                                                                                                                                                                                                                                      |
| `issue`          | body | integer (int64) | —        | Issue is the number of the issue on Repo this run resolves.                                                                                                                                                                                                                                      |
| `mode`           | body | string          | —        | Mode is what the run may do to the repository: `build` edits, commits and pushes its branch; `plan` reads the repository and answers with a plan, writing nothing — its sandbox is handed a credential that can only read and no push step runs, and the plan arrives as the run's final status. |
| `model`          | body | string          | —        | Model is the model the run's agent thinks with, by the id GET /v1/models lists.                                                                                                                                                                                                                  |
| `project`        | body | string          | —        | Project scopes the run to one board's work when the org keeps more than one.                                                                                                                                                                                                                     |
| `prompt`         | body | string          | —        | Prompt is the task, in the words you would use with a colleague who has the checkout open.                                                                                                                                                                                                       |
| `reply`          | body | agent.Reply     | —        |                                                                                                                                                                                                                                                                                                  |
| `reply.channel`  | body | string          | —        | Channel is the room inside that workspace, and it is what decides whether there is an address at all.                                                                                                                                                                                            |
| `reply.provider` | body | string          | —        | Provider is the transport the conversation is on — slack, discord, telegram, teams — and it is what decides who can carry the text at all.                                                                                                                                                       |
| `reply.thread`   | body | string          | —        | Thread narrows the address to one thread inside the channel — on Slack the parent message's ts, the same value a reply carries as thread\_ts.                                                                                                                                                    |
| `reply.turn`     | body | string          | —        | Turn is the turn that renders a run started here: the session whose one message the run's progress and its outcome are shown in.                                                                                                                                                                 |
| `reply.user`     | body | string          | —        | User is the platform's id for the person the conversation is with — whose run it is.                                                                                                                                                                                                             |
| `repo`           | body | string          | —        | Repo is what to work on: a repository's name, `owner/name` in the caller's own org, or the site a repository serves (`hanzo.ai`), as the person said it.                                                                                                                                         |
| `targetId`       | body | string          | —        | TargetID routes the run to a registered machine the org has claimed instead of to a sandbox in our cluster.                                                                                                                                                                                      |
| `task`           | body | string          | —        | Task is Prompt under the name a caller asking for work tends to reach for.                                                                                                                                                                                                                       |
| `timeoutSeconds` | body | integer (int64) | —        | TimeoutSeconds bounds the whole run.                                                                                                                                                                                                                                                             |
| `tool`           | body | string          | —        | Tool is which harness runs the prompt — dev \| claude \| codex \| python \| node — and Desktop is whether the run needs a screen.                                                                                                                                                                |

## Response

| Status    | Body                | Meaning  |
| --------- | ------------------- | -------- |
| `202`     | agent.CodingStarted | accepted |
| `default` | problem-details     | refused  |

`202` body — 5 fields.

| Field       | In   | Type    | Always | Description                                                                                                                                     |
| ----------- | ---- | ------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `branch`    | body | string  | —      | Branch is the ref the run will push its work to, and the ONLY ref it is permitted to write.                                                     |
| `repo`      | body | string  | —      | Repo is the repository the run was admitted against, echoed back as the engine resolved it.                                                     |
| `routed`    | body | boolean | —      | Routed says the run went to one of the org's own registered machines rather than to a sandbox in our cluster.                                   |
| `sessionId` | body | string  | —      | SessionID is the run's handle: its durable record, and the root its live progress streams under at /v1/agent/sessions/stream?root=\<sessionId>. |
| `targetId`  | body | string  | —      | TargetID names that machine when Routed is true, and is empty otherwise.                                                                        |

Failure carries the platform error shape — see [Errors](https://docs.hanzo.ai/docs/errors).

## Examples

**CLI**

```bash
hanzo agent coding
```

**SDK**

**.ts**

```ts
import { Configuration, AgentApi } from 'hanzoai';

const api = new AgentApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postAgentCoding({ after: "<after>", agentRef: "<agentRef>" });
```

**.py**

```python
from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import AgentApi

client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = AgentApi(client).post_agent_coding(after="<after>", agent_ref="<agentRef>")
```

**.go**

```go
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.AgentAPI.PostAgentCoding(context.Background()).Execute()
if err != nil {
	return err
}
```

**.rs**

```rust
use hanzo_client::apis::{configuration::Configuration, agent_api};

let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();

let result = agent_api::post_agent_coding(&cfg, Default::default()).await?;
```

**.java**

```java
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.AgentApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new AgentApi(client).postAgentCoding();
```

**HTTP**

```bash
curl -X POST https://api.hanzo.ai/v1/agent/coding \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "after": "<after>",
       "agentRef": "<agentRef>"
     }'
```

**MCP**

MCP reaches **agent** through the `agent` tool, which names its 38 operations with its own verbs — this one among them, under a name only MCP declares. `describe` explains any of them:

```bash
curl -X POST https://api.hanzo.ai/v1/mcp \
  -H "Content-Type: application/json" \
  -d '{
       "jsonrpc": "2.0",
       "id": 1,
       "method": "tools/call",
       "params": {
         "name": "describe",
         "arguments": {
           "op": "list_agents"
         }
       }
     }'
```

---

[Agent API](https://docs.hanzo.ai/docs/openapi/agent) · [All Hanzo APIs](https://docs.hanzo.ai/docs/openapi) · [Interactive reference](https://docs.hanzo.ai/docs/openapi/reference)
