Compute wire formats and artifact references
How to send API messages as JSON, keep encrypted file content separate, and parse each returned file by its media type.
Treat an API message and the file it describes as separate things. Send the operation's JSON metadata to the API, and transfer or retrieve encrypted artifact bytes through that artifact's authority.
These rules tell your agent and the Kit how to encode, transfer and parse the declared data. They do not make a decoded result semantically correct; your agent still applies the task's acceptance rule.
Metadata messages
| Message | Media type and shape |
|---|---|
| REST JSON request | application/json, encoded as UTF-8; the operation defines the body schema |
| REST JSON success | application/json; an object containing ok: true and data |
| REST typed error | application/json; an object containing ok: false, error and p_next_action |
| MCP request | application/json; JSON-RPC with jsonrpc: "2.0", a method and its declared parameters |
| Agent-event response | The API description declares application/json and text/event-stream representations; use the returned media type |
For MCP, include both application/json and text/event-stream in the request's Accept header. That transport requirement is not a promise of streamed model tokens or an inline result file.
JSON, newline-delimited JSON, and server-sent events are different encodings. Do not parse an event stream as one JSON object. Likewise, a .jsonl filename does not authorize sending several top-level JSON objects to a REST operation that requires one object.
For tabular artifacts, JSONL, Parquet, and Arrow are separate codec choices. Use one only when the selected operation's input or output contract names it; a filename does not establish format support.
The Compute JSON reader rejects malformed UTF-8, duplicate object keys, and trailing JSON. Use the declared object schema and preserve nested strictness. Its 65,536-byte request bound includes metadata, not just the content you consider useful.
Artifact bytes stay out of metadata
A job's input.source contains kind: "encrypted_artifact" and artifact_id. Its input.public_bounds describes files, ciphertext_bytes and estimated_input_tokens. It is not a container for an inline document, image, audio file, source archive or local path.
The job's output contract identifies output_schema_id. Use the input and output requirements for that exact operation. A file extension does not establish that the operation accepts every codec, document feature, table type or language that the wider format permits.
Do not add generic input.format, input.item_id_field, input.snapshot or top-level output fields to LithiJobV1. Those are not declared members of that request. A convenience configuration in another interface must be converted to the actual operation's schema before submission.
The result endpoint returns an encrypted_artifact_id and evidence digests. That identifier is neither a URL nor the contents of a result bundle. Do not infer a fixed directory layout, seven added tabular columns or a particular file format from the result projection alone.
Identifiers and digests
| Field or family | Exact format |
|---|---|
| Job, batch, account and quote IDs | UUID strings where the operation declares format: uuid |
| Artifact preparation/completion IDs and result artifact references | ^artifact_[A-Za-z0-9_-]{16,96}$ |
| Upload IDs | ^upload_[A-Za-z0-9_-]{16,96}$ |
Digest | ^[a-f0-9]{64}$ |
output_schema_id | ^[A-Za-z][A-Za-z0-9._-]*$, 1–160 characters |
| Capability and operation names | ^[a-z][a-z0-9._-]*$, 1–80 characters |
A digest is lowercase hexadecimal, not Base64. Preserve identifier case; do not translate, truncate or rebuild a returned identifier. Constraints can differ between a reusable contract and an operation-specific field, so apply the schema selected by the operation.
An artifact identifier does not authorize a download. Keep the object reference and its access authority separate. Do not turn a local file path or a credential-bearing URL into an artifact ID.
Dates, durations and money
| Field | Representation | Example meaning |
|---|---|---|
execution.deadline_at | Date-time string | 2026-09-10T12:00:00Z identifies an instant, not a duration |
expires_in_seconds | Integer seconds | 60 requests a validity interval of 60 seconds |
capacity.max_wait_seconds | Integer seconds | 300 is a five-minute bound, not a timestamp |
maximum_charge_micro_usd | Integer millionths of a US dollar | 1000000 represents a $1 maximum, not a quoted rate |
gross_micro_usd | Integer millionths of a US dollar | Preserve the integer and associated currency when reading usage |
These examples cover individual fields, not complete requests. Do not substitute an ISO duration such as PT6H for a date-time field, or a decimal-dollar object for an integer micro-USD field. A quote's validity interval and an execution deadline remain separate.
Absent values and null
A missing field, JSON null, an empty string and an empty array have different meanings. LithiJobV1.receipt_id is required but may be null. Optional event fields and pagination next_cursor are omitted when absent; their declared schemas do not accept null.
A result field that permits null must be interpreted using that result's schema. Do not convert a missing response, parse failure or unknown state into an accepted empty result. Keep the original job reference and investigate the failed read before starting replacement work.
Recover from a format error
For HTTP 415 with UNSUPPORTED_MEDIA_TYPE, check the operation's required media type and encoding. For 400 with INVALID_REQUEST, check the complete body against its schema, including required fields, patterns and nullability. Do not keep retrying unchanged malformed bytes.
Use the canonical Compute OpenAPI document to select exact message and projection schemas. Treat document, media and tabular content support as an operation-specific contract, not a platform-wide promise inferred from a filename.