Skip to main content
Use manual runs when you need explicit control or when the provider is not OpenAI or Anthropic. For normal OpenAI or Anthropic calls, prefer margovia.openai(client) or margovia.anthropic(client). Those tracked clients can read provider usage and report cost automatically. Use wrappers or explicit provider helpers when you need to migrate existing call sites.

Start and complete a run

import { Margovia } from "@margovia/sdk";

const margovia = new Margovia();

const run = await margovia.startRun({
  name: "generate_report",
  userId: "user_123",
  customerId: "workspace_123",
  customerName: "Acme Inc.",
  customerPlan: { name: "enterprise", monthlyUsd: 499 },
  properties: {
    reportType: "weekly_margin"
  }
});

await run.trackCost({
  provider: "serpapi",
  label: "search_tool",
  costUsd: 0.01,
  status: "success"
});

await run.complete({ outcome: "report_generated" });
Manual runs stay running until you explicitly call run.complete(...) or run.fail(...). Cost events alone do not close the run.

Track failures

try {
  await doWork();
  await run.complete({ outcome: "done" });
} catch (error) {
  await run.fail({
    error: error instanceof Error ? error.message : "Unknown error"
  });
  throw error;
}

Use track for workflow lifecycle

track wraps a function, opens a run, and completes or fails it automatically. It does not read provider token usage by itself.
const result = await margovia.track({
  name: "generate_report",
  customerId: "workspace_123",
  outcome: "report_generated",
  fn: async () => generateReport()
});
track is the safest option for custom workflows because it automatically completes the run on success and fails it when fn throws. If the function calls OpenAI or Anthropic, use wrapped clients inside:
const openai = margovia.wrapOpenAI(new OpenAI());

await margovia.track({
  name: "generate_report",
  customerId: "workspace_123",
  outcome: "report_generated",
  fn: () => openai.chat.completions.create({ model: "gpt-5-mini", messages })
});
Do not use track around a raw provider client unless you also report cost manually.

Track multiple provider calls

Use one manual run when several calls belong to the same user-facing workflow.
const run = await margovia.startRun({
  name: "research_report",
  customerId: `workspace_${workspace.id}`,
  customerName: workspace.name,
  customerPlan: { name: workspace.plan, monthlyUsd: workspace.planMonthlyUsd }
});

try {
  await run.step("outline", () => createOutline());
  await run.step("source_search", () => searchSources());
  await run.step("final_draft", () => draftReport());

  await run.complete({ outcome: "report_generated" });
} catch (error) {
  await run.fail({
    error: error instanceof Error ? error.message : "Unknown error"
  });
  throw error;
}
run.step(...) attaches wrapped provider calls to the existing run instead of creating separate runs.

Customer IDs

Send a stable, namespaced customer ID:
customerId: `workspace_${workspace.id}`
customerId: `org_${organization.id}`
customerId: `stripe_${stripeCustomer.id}`
Avoid raw IDs like "1" unless that is the stable ID you use across your whole system. Margovia will not rewrite the value.