Skip to content

SDK reference

Three SDKs: TypeScript (@lantern/sdk), Python (lantern-sdk, imported as lantern) and Go (github.com/dshakes/lantern/packages/sdk-go). They cover agents, runs, sessions, connectors, budgets, evals, experiments, marketplace, MCP, receipts, feedback, rehearsals and sandbox VMs. The TypeScript client has the most surface; the listings below show what each one exposes.

The SDKs wrap the REST API in typed methods, so you call client.runs.create(...) instead of writing HTTP. Use them to trigger agents from your app, wire runs into your backend, or script bulk operations. For the raw endpoints see the API reference.

Terminal window
# in your checkout of github.com/dshakes/lantern
( cd packages/sdk-ts && npm install && npm run build )
# in your project: a file path, not the registry
npm install /path/to/lantern/packages/sdk-ts

After that, import { LanternClient } from "@lantern/sdk" resolves to the built dist/. Rebuild after pulling changes.

import { LanternClient } from "@lantern/sdk";
const client = new LanternClient({
apiKey: process.env.LANTERN_API_KEY, // hlx_live_...
baseUrl: process.env.LANTERN_API_URL, // e.g. http://localhost:8080
});

With no constructor options the SDK reads LANTERN_API_KEY and LANTERN_API_URL. If LANTERN_API_URL is unset, the base URL defaults to https://api.lantern.run, so set it for a self-hosted control plane. (LANTERN_RUNTIME=true is a different switch: the platform sets it inside a running agent to enable the production sidecar.)

import type { Run } from "@lantern/sdk";
// Create a run (create() returns an event stream instead when you pass stream: true)
const run = (await client.runs.create({
agent: "research-agent",
input: { topic: "quantum computing" },
})) as Run;
console.log(run.id, run.status); // queued
// Stream events for the run
for await (const event of client.runs.events(run.id)) {
console.log(event.kind, event.stepId, event.data);
// kinds include step_started, step_completed, step_failed, tool_call, tool_result, llm_delta, log, approval, end
}
// Fetch final result
const finished = await client.runs.get(run.id);
console.log(finished.status, finished.output);
// Create a session
const session = await client.sessions.create({ agent: "my-agent" });
// Stream a message turn
for await (const chunk of client.sessions.streamMessage(session.id, {
content: "What is the capital of France?",
})) {
// chunk.type is "delta" | "completed"; a server-side message_error throws MessageStreamError
if (chunk.type === "delta") process.stdout.write(chunk.delta);
if (chunk.type === "completed") console.log("\nDone:", chunk.usage);
}
// Non-streaming send: returns immediately; the reply arrives on sessions.events()
await client.sessions.sendMessage(session.id, {
content: "Follow-up question",
});
// Cleanup
await client.sessions.delete(session.id);
client.agents // create, get, list, delete
client.runs // create, get, list, cancel, events, signal, forecast
client.sessions // create, get, list, sendMessage, streamMessage, events, stop, delete, close
client.connectors // list, get, execute, test, uninstall
client.budgets // upsert, get, list, delete
client.evalSuites // upsert, list, get, delete
client.evalRuns // record, list
client.evalBaselines // set, get
client.experiments // create, list, get, recordOutcome, conclude
client.marketplace // list, get, publish, fork, star, unstar
client.mcp // listServers, getServer, attach, listAttachments, detach
client.receipts // issue, verify
client.feedback // submit, listForRun, summaryForAgent
client.rehearsals // pull
client.runtime // schedule, list, get, terminate, exec, execStream, pause, resume, fork, listFiles, readFile, writeFile
import { LanternApiError, MessageStreamError } from "@lantern/sdk";
try {
await client.runs.create({ agent: "my-agent", input: {} });
} catch (err) {
if (err instanceof LanternApiError) {
console.error(err.status, err.message);
}
}
// Errors during a session stream
try {
for await (const chunk of client.sessions.streamMessage(id, { content: "hi" })) {
// ...
}
} catch (err) {
if (err instanceof MessageStreamError) {
console.error("stream error:", err.message);
}
}

Retries are built in. The TypeScript client retries HTTP 429, 503 and network errors up to 3 attempts with full-jitter backoff (500 ms base, 4 s cap). It never retries other 4xx or 5xx. There is no separate @lantern/retry package.

Sandbox VMs live under client.runtime in TypeScript and Python; Go has ScheduleVM, PauseVM, ResumeVM, ForkVM, ListFiles, ReadFile and WriteFile. See Sandbox lifecycle.

Terminal window
# from the root of your checkout
pip install ./packages/sdk-python
# optional: LangChain deepagents sandbox backend (lantern.integrations.deepagents_sandbox)
pip install "./packages/sdk-python[deepagents]"
from lantern import LanternClient
client = LanternClient(
api_key="hlx_live_your_key", # or LANTERN_API_KEY env var
base_url="http://localhost:8080", # or LANTERN_API_URL env var
)
# Request methods are coroutines: call from async code, or asyncio.run(main())

LanternClient is built on httpx.AsyncClient: every request method is async def; runs.events, sessions.stream_events and runtime.exec_stream return async iterators (async for). Use async with LanternClient(...) as client or call await client.close().

run = await client.runs.create(agent="research-agent", input={"topic": "AI safety"})
print(run.id, run.status) # queued
client.agents # create, get, list, delete
client.runs # create, get, list, cancel, events, signal, forecast
client.sessions # create, get, list, send_message, stream_events, stop, delete, close
client.connectors # list, get, execute, list_actions
client.budgets # upsert, get, delete, list_all
client.evals # upsert_suite, list_suites, get_suite, delete_suite, record_run, list_runs, set_baseline, get_baseline
client.experiments # create, list, get, record_outcome, conclude
client.marketplace # list, get, publish, fork, star, unstar
client.mcp # list_servers, get_server, attach, detach, list_attachments
client.receipts # issue, verify
client.feedback # submit, list_for_run, summary_for_agent
client.rehearsals # pull
client.runtime # schedule, list, get, terminate, exec, exec_stream, pause, resume, fork, list_files, read_file, write_file
resp = await client.agents.list()
for agent in resp.agents:
print(agent.name, agent.current_version_id)

Inside an agent bundle, ctx gives you durable steps, LLM calls, tools, memory and connectors. Each step is journaled, so a crashed run resumes instead of restarting:

import { agent, step } from "@lantern/sdk";
export default agent<{ query: string }>({
name: "my-agent",
model: "auto",
async run({ input, ctx }) {
// Durable step — journaled, idempotent, resumable on crash
const data = await step("fetch-data", async () => {
return ctx.tools.web.search(input.query);
});
// LLM call — addressed by capability; the model router picks the vendor model
const summary = await step("summarize", async () => {
return ctx.llm.complete({
messages: [{ role: "user", content: `Summarize: ${data}` }],
capability: "reasoning-small",
});
});
return { summary };
},
});

Use capability names like auto, reasoning-large, chat-small, vision-large. Do not hardcode a vendor model. The model router maps the capability to a concrete model at call time. See Models for the full list.

const results = await step.map("search", queries, async (query) => {
return ctx.tools.web.search(query);
});
// Blocks until a human grants or denies.
await ctx.approval.request({
reason: "Send this email to 500 users?",
expiresAt: "2026-12-01T00:00:00Z",
});
// Reaching this line means it was granted. Denial or timeout throws LanternError.