Use Jinn from an agent
Updated 2026-10-07
This page is for coding agents and the people who set them up. It says how to read these docs, how to call Jinn without a person watching, and how to tell what went wrong.
Read the docs
- Every page is Markdown at the same address with
.mdadded, for example /runs.md. A request withAccept: text/markdowngets the Markdown too. - llms.txt lists every page with one line about it. llms-full.txt holds all of them in one file.
- openapi.json describes every route, field, error code and limit of the API. Each operation has an
operationId.
Authenticate
Give the agent an API key in JINN_KEY. An owner makes keys in the console under Account. Use a run key when the agent only starts runs of named functions. Use an admin key when it also publishes functions. Keys never expire; revoke one in the console when the agent no longer needs it.
The agent never needs a model vendor's key. Providers hold those, and people add them in the console or with jinn provider.
Use the CLI
Install it with:
curl -fsSL https://github.com/usejinn/jinn-cli/releases/latest/download/install.sh | sh
Add --json to any command. Results are printed as one JSON document. A stream (jinn run without --detach, jinn logs) is printed as JSON lines. The CLI never prompts when stdin is not a terminal.
$ jinn run support-triage --prompt "Ticket #4812: charged twice" --in ./in --out ./result --json
{"run":{"id":"run_fc8b8312336d7d3d0c6cace0",…,"state":"queued",…},"type":"run"}
{"run":{"id":"run_fc8b8312336d7d3d0c6cace0",…,"state":"running",…},"type":"run"}
{"at":"2026-10-07T13:03:18.206042976Z","kind":"system","text":"You answer billing tickets for Acme. …","type":"log"}
{"arguments":"{\"email\":\"maria.lopez@brightpath.io\"}","at":"2026-10-07T13:03:24.738990358Z","id":"toolu_01AradMuJxWMfkM52RpwN8os","kind":"tool_call","name":"lookup_customer","type":"log"}
{"run":{"id":"run_fc8b8312336d7d3d0c6cace0",…,"state":"succeeded",…,"output":{…},…},"type":"run"}
{"dir":"./result","file_count":2,"files":[{"path":"actions.json","bytes":154},{"path":"reply.md","bytes":859}],"type":"output"}
Line type | Holds |
|---|---|
run | The run, as GET /v1/runs/{id} returns it. Printed when it is queued, when it starts and when it ends. |
log | One log event: at, kind and the event's fields. |
output | The folder the output was unpacked into, and its files. |
Errors are one JSON object on stderr: {"error": "…", "exit": 3, "status": 402, "code": "no_credit"}.
| Exit status | Meaning |
|---|---|
| 0 | Done. For jinn run, the run succeeded. |
| 1 | The run failed. Its last run line has failure and detail. |
| 2 | The command was used wrongly. |
| 3 | The API refused the request. code says why; see API errors. |
| 4 | Anything else: the network, a local file. |
To start a run and come back later, use --detach, then jinn show RUN --json until state is succeeded or failed.
Use the API
The API is plain HTTPS and JSON at https://api.usejinn.com/v1. A refused request has a stable code:
{"code": "no_credit", "error": "this account has no credit left; an owner can add credit in the console"}
Switch on code, not on the message. Retry conflict and internal. Do not retry the others without a change. For results, poll GET /v1/runs/{id}, or start the run with a webhook and wait for the event.
Write a function an agent can rely on
- Name every file the run must return in
output_manifest. The agent inside the run cannot finish until they exist, so the caller never gets a half-done result. - End the system prompt with what to write where, then "call submit_result".
- Keep
timeout_minutesclose to what the work takes. A run that hangs costs until its timeout. - Give setup commands exact package versions, so every run starts the same.