@sapiom/tools
v0.8.1
Published
Typed client for Sapiom capabilities (sandboxes, repositories, agent, file storage, …) — the same tools your agents call over MCP, callable from your code, auth'd to your tenant.
Readme
@sapiom/tools
A typed TypeScript client for Sapiom capabilities — sandboxes, git repositories, coding agents, file storage, content generation, search, and orchestrations — authenticated to your tenant.
These are the same capabilities your Sapiom agents call as tools; this package makes them callable directly from your own code.
npm install @sapiom/tools
# or
pnpm add @sapiom/toolsQuickstart
import { createClient } from "@sapiom/tools";
const sapiom = createClient({ apiKey: process.env.SAPIOM_API_KEY });
// Create a repo, have a coding agent build into it, then publish.
const repo = await sapiom.repositories.create("landing-page");
const run = await sapiom.agent.coding.run({
task: "Build a one-page marketing site in index.html.",
gitRepository: repo, // cloned into the run's sandbox at /workspace/landing-page
});
if (run.result?.success) {
const { sha } = await repo.pushFromSandbox(run.sandbox, {
message: "build: landing",
});
console.log("published", sha);
}Authentication
There are two ways to authenticate, both exposing the identical capability surface:
- Explicit — pass a key to
createClient. This is the standalone entry point:const sapiom = createClient({ apiKey: process.env.SAPIOM_API_KEY }); await sapiom.sandboxes.create({ name: "demo" }); - Ambient — import the namespaces directly and they resolve credentials from
SAPIOM_API_KEY(or, inside a Sapiom workflow step, from the client the runtime provides):import { sandboxes, repositories, agent } from "@sapiom/tools"; await sandboxes.create({ name: "demo" });
Attribution
Calls can be attributed to an agent and trace so they show up correctly in your transaction history. Attribution is set once, on the client — not per call:
const sapiom = createClient({
apiKey: process.env.SAPIOM_API_KEY,
attribution: { agentName: "digest-bot", traceId },
});
// every call this client makes is now attributed to digest-bot / traceIdInside a Sapiom workflow you don't set this at all — the runtime constructs the client with the running execution's attribution, so every tool call is attributed automatically.
If a single process makes calls on behalf of more than one agent or trace, derive a client per context with sapiom.withAttribution({ ... }).
Capabilities
Each capability is a namespace, importable from the barrel or its own subpath (e.g. @sapiom/tools/sandboxes). Every capability has its own README with usage details, preconditions, and gotchas the type signatures can't express — read it before first use.
| Namespace | What it is | Docs |
| ------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| sandboxes | Isolated, ephemeral compute | src/sandboxes |
| repositories | Private, in-network git repos | src/repositories |
| agent | Coding agents (LLM execution) | src/agent |
| fileStorage | Tenant-scoped object storage (presigned URLs) | src/file-storage |
| contentGeneration | Media generation (images + video; audio soon), with optional storage | src/content-generation |
| search | Search the web (webSearch), read a page (scrape), and look up professional emails (emailSearch) | src/search |
| orchestrations | Run a deployed orchestration, or dispatch one from a step and await its result | src/orchestrations |
| database | On-demand Postgres databases, returned with direct connection credentials | src/database |
Composing capabilities
Capabilities are designed to work together. A coding agent run hands back the live Sandbox it executed in, and a Repository can publish a working tree straight from that sandbox:
const run = await agent.coding.run({ task, gitRepository: repo });
await repo.pushFromSandbox(run.sandbox);A useful pattern: let the agent do the open-ended work (writing files) and perform exact, repeatable actions — committing, pushing, deploying — in your own code rather than in the agent's prompt. The agent produces the changes; pushFromSandbox publishes them deterministically.
Some compositions need nothing but a param. contentGeneration.images.create takes an optional storage, and each generated image is persisted into fileStorage as it returns — handing you a durable fileId with no extra call:
const out = await contentGeneration.images.create({
prompt: "a logo",
storage: { visibility: "private" },
});
const { downloadUrl } = await fileStorage.getDownloadUrl(
out.images![0].fileId!,
);License
MIT
