Ingram Cloud

Documentation

Coding agents

Coding agents

What to hand a coding agent so its first draft compiles, and how to scope the token it runs with.

Give it the docs

Every page in these docs has a raw Markdown twin. There is nothing to scrape and no docs MCP server to install:

  • /llms.txt — the index, generated from the same manifest this console renders. Base URL, version header, auth, the OpenAPI URL, then every page linked to its Markdown.
  • /docs/<slug>.md — any page as plain Markdown. Requesting /docs/<slug> with Accept: text/markdown returns the same bytes.
  • /openapi.json — emitted from the live routes. Exact paths, request and response shapes, and every error code enumerated on the Error schema. When prose and spec disagree, the spec is right.
curl https://cloud.ingram.tech/llms.txt
curl https://cloud.ingram.tech/docs/runs.md
curl https://api.cloud.ingram.tech/openapi.json

Point the agent at /llms.txt first, then the two or three pages it names.

Paste this into your agent's instructions

Drop it in AGENTS.md, CLAUDE.md, .cursorrules, or whatever your harness reads:

## Ingram Cloud

This project integrates Ingram Cloud (hosted AI agents over one REST API).

- Docs index: https://cloud.ingram.tech/llms.txt — any page is also raw
  Markdown at https://cloud.ingram.tech/docs/<slug>.md. Read the relevant
  pages before writing integration code.
- OpenAPI (source of truth): https://api.cloud.ingram.tech/openapi.json
- Base URL: https://api.cloud.ingram.tech — every endpoint under /v1.
- Every request sends `Authorization: Bearer $IC_TOKEN` and
  `IC-Api-Version: 2026-05-01`.
- An **agent** (`agt_`) is the reusable design; a **smith** (`smt_`) is one
  end-user's running clone. Never mix the two words.
- Chat goes over the OpenAI-compatible surface (`POST /v1/chat/completions`,
  or the `openai` SDK with `baseURL` set to the /v1 base). Management calls go
  through `@ingram-cloud/sdk`. Don't hand-roll fetch wrappers.
- $IC_TOKEN is a tenant-admin token: server-side only, never in client code,
  never committed.

Give it the typed SDK

Install @ingram-cloud/sdk:

import { IngramCloud } from "@ingram-cloud/sdk/client";

const ic = new IngramCloud({ token: process.env.INGRAM_CLOUD_TOKEN! });
const smith = await ic.smiths.create({ external_id: "user-42" });

Method inputs are inferred from the same Zod schemas the API validates requests with, so an invented field is a type error in the agent's editor rather than a 422 at runtime. Run tsc as the agent's inner loop.

The OpenAI-compatible surface needs no new client at all: against an existing openai integration, only the baseURL changes. That is what standards-first design buys here — the model's existing knowledge of the wire is correct.

Give it a scratch project

A project is a tenant, and a tenant-admin token is bound to its project inside the JWT, so a token minted in a scratch project is cryptographically incapable of reading production. Deleting the project ends the experiment.

With an organization key:

# Authorization: organization key (server-side / IaC only)
curl https://api.cloud.ingram.tech/v1/organization/projects \
  -H "Authorization: Bearer $IC_ORG_TOKEN" \
  -H "IC-Api-Version: 2026-05-01" -H "Content-Type: application/json" \
  -d '{ "name": "acme-agent-scratch" }'
# → 201 { "id": "proj_…", … }

# Authorization: organization key (server-side / IaC only)
curl https://api.cloud.ingram.tech/v1/organization/projects/proj_…/tokens \
  -H "Authorization: Bearer $IC_ORG_TOKEN" \
  -H "IC-Api-Version: 2026-05-01" -H "Content-Type: application/json" \
  -d '{ "name": "coding agent scratch" }'
# → 201 { "token": "tha_live_…", "scopes": ["tenant:*"] }

Hand the agent that tha_live_…, not the org key: the org key mints tokens for every project you own. DELETE /v1/organization/projects/{pid} deletes the project.

Two more things to set:

  • A cost budget with action: "block" on the scratch project, so a retry loop stops at the budget rather than spending your balance.
  • Short ttl_seconds on the token. DELETE /v1/tenant/tokens/{id} revokes it immediately if it leaks.

Other credentials are already scoped: a smith token the agent mints for browser code can only touch that one smith, and 403 tenant_token_required blocks a smith token from reading or changing configuration.

Let it read what happened

  • GET /v1/runs — every run, filterable by smith_id, agent_id, status. A failed run carries why it failed.
  • GET /v1/events — the append-only feed of run lifecycle, tool calls, approvals and budget thresholds. A tool that never ran and a tool that ran and threw produce different events.
  • The run's traceGET /v1/runs/{rid}/trace, the timed span tree: which model call, which tool, how long, what it cost.
  • X-Request-Id on every response, and a stable code on every error.

A read-only token (*:read scopes only) covers all of it, so the debugging loop needs no write access.

Ingram Cloud inside the coding agent

Deploy an agent as an mcp deployment and any MCP client that speaks remote servers (Claude Code, Claude, ChatGPT) can call it as a tool, with OAuth discovery handling credentials.

claude mcp add --transport http acme \
  https://api.cloud.ingram.tech/v1/deployments/dep_…/mcp

Each caller talks to their own smith, so the isolation you built for end-users holds for your team.

Working the loop

  • Pin IC-Api-Version: 2026-05-01 on every request. Requests without it get the latest version.
  • Let the agent execute a real curl against the scratch project rather than only writing code.
  • On a disagreement about a field name, point it at /openapi.json.
  • Watch for agent/smith confusion. Wrong-noun code compiles and looks correct; the instruction block above exists to prevent it.

Next: Quickstart for the three-curl path, or the TypeScript SDK for the typed one.