> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://developer.deel.com/cli/agents/workflows/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.deel.com/_mcp/server. # Agent workflows > Patterns for AI agents that discover, call, and recover with the Deel CLI This page describes how an agent should use the CLI: discover before calling, build bodies from skeletons, read results as data, classify errors, retry safely, follow jobs, and stay within guardrails. The [instruction block](/cli/agents/setup#add-the-instruction-block) encodes these patterns in a form agents follow. ## Discover before calling The recommended order is: list, read the contract, generate the body, call, read the result. ```bash deel --help # 1. what exists deel adjustments create --help # 2. which variants deel adjustments create --invoice --help --json # 3. the exact contract deel adjustments create --invoice --generate-input # 4. a body to fill in deel adjustments create --invoice --input file://body.json --fields adjustment_id,status # 5. call and read ``` Steps 1 to 4 run offline and do not need a token or network access. The contract from step 3 tells the agent how to build the body: | `body.kind` | The agent should | | ------------ | ----------------------------------------------------------------------------- | | `none` | Pass parameters as flags only | | `json` | Fill the skeleton object and pass it with `--input` | | `json-array` | Build a JSON array, one item per record, and pass it as a file or inline JSON | | `multipart` | Pass text fields with `--input` and files with `--file field=@path` | ## Build request bodies from skeletons `--generate-input` prints every field with a typed placeholder. An agent should write the skeleton to a file, replace the values it knows, remove optional fields it does not need, and pass the file back. ```bash deel adjustments create --invoice --generate-input > body.json # ... the agent edits body.json ... deel adjustments create --invoice --input file://body.json ``` Values are validated before the request is sent. A wrong enumeration value or a non-numeric amount fails locally with `input.enum` or `input.type`, without a round trip to the API. ## Read results as data Ask for only what the next step needs. ```bash deel adjustments create --invoice --input file://body.json --jq '.adjustment_id' --raw # one bare value deel jobs list --fields job_id,status # a projected envelope deel jobs status --job_id="$JOB_ID" --jq '.items[] | select(.status == "FAILED")' # only the failures ``` `--quiet` prints identifiers only, one per line, which is the form to pipe into the next command. ## Classify errors On failure the exit status is 1 and stderr carries a JSON envelope. The `code` prefix tells the agent what kind of problem it is and whether it can fix it alone. | `error.code` | Meaning | Agent action | | -------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------- | | `input.*`, `usage.*` | The command line or body is wrong | Fix locally using `--help --json`, then retry | | `auth.*` | No token, invalid token, or no keychain | Stop and report; a person must provide or fix the token | | `http.400`, API validation codes | The API rejected the body; `message` lists the fields | Fix the listed fields, then retry | | `http.401`, `http.403` | The token lacks access | Stop and report; a scope or policy decision is needed | | `http.404` | The referenced record does not exist | Re-check identifiers; do not retry blindly | | `http.429`, `http.5xx` | Rate limited or upstream failure after the CLI's own retries | Wait, then retry the same command | | `network.*` | Transport, TLS, or timeout | Report the environment problem | ```json { "error": { "code": "input.enum", "message": "--type must be one of: BONUS, COMMISSION, DEDUCTION, EXPENSE, OTHER, OVERTIME, TIME_OFF, VAT" } } ``` Every API error includes `request_id`. An agent should quote it when it reports a failure so that support can locate the request. See [Errors and exit codes](/cli/usage/errors) for the full list. ## Retry safely Every mutating command carries an idempotency key derived from its content. Re-running the identical command after a timeout or an ambiguous failure sends the same key, and the API returns the original result instead of creating a second record. An agent does not need to check whether a write completed successfully before retrying it. The CLI already retries `429` and `5xx` responses up to three times. An agent that still sees `http.429` should wait longer before its own retry rather than loop immediately. See [Idempotency and retries](/cli/usage/idempotency-and-retries). ## Bulk operations and jobs Bulk commands return `202` with a `job_id`. The agent should capture the id, poll until a terminal status, and then inspect failed items. ```bash JOB_ID=$(deel adjustments create-bulk --invoice --input file://batch.json --quiet) until deel job status "$JOB_ID" --jq '.status' --raw | grep -Eq 'SUCCEEDED|FAILED'; do sleep 5; done deel jobs status --job_id="$JOB_ID" --jq '.items[] | select(.status == "FAILED")' ``` Batches are limited to 50 items per request; the CLI rejects longer arrays with `usage.max_items` before sending. An agent should split larger sets and use `external_id` on each item to correlate results with its own records. See [Asynchronous jobs](/cli/usage/async-jobs). ## Guardrails * **Least privilege.** Give the agent a token with only the scopes its tasks need. A `403` is a signal to ask a person, not to try another route. * **Demo by default.** Keep `DEEL_ENV=demo` in the agent's environment. Production runs are an explicit change made by a person. * **Review before bulk writes.** Have the agent show the batch file before running `create-bulk`. * **No token handling.** The agent runs `deel` commands; it never reads, prints, or moves the token. `deel auth status` masks it to its last four characters. * **Keep logging on.** The local log is the record of what the agent did. ## Auditing an agent session The CLI writes one newline-delimited JSON (NDJSON) line per request to its [local log](/cli/usage/logging#log-location): timestamp, command, method, URL path, status, duration, request id, and idempotency key, with the token masked and the body omitted. To review what an agent did: ```bash # macOS jq -r '[.ts, .command, .method, .status, .request_id] | @tsv' ~/Library/Logs/deel/deel.log # Linux jq -r '[.ts, .command, .method, .status, .request_id] | @tsv' ~/.local/state/deel/logs/deel.log ``` Set `DEEL_LOG_DIR` in hosted environments to a directory you collect, or upload the log as a CI artifact. Response bodies are never logged unless `--log-bodies` is passed, so the log can be kept without special handling. ## Next steps #### [Set up a coding agent](/cli/agents/setup) Install, token, environment, and the instruction block #### [Scripting and CI](/cli/guides/automation) The same patterns for unattended pipelines > Build apps and integrations that extend and enhance the Deel services.