Skip to content
Euler Docs

Integrate Euler in 15 minutes

This quickstart uses your hosted Euler API plus the generated Python and TypeScript SDKs. It covers the three customer flows most teams need first: register a third-party MCAP source, plan a gated ingest run, then search and save the useful episodes as an eval-ready slice.

Before you start

Set the API base and token once. Health checks are public; /v1 routes require the bearer token configured for your Euler tenant.

export EULER_BASE_URL="https://api.euler.sudotank.com"
export EULER_API_TOKEN="<tenant-api-token>"
export EULER_PROJECT_ID="warehouse-arm"
export EULER_SOURCE_ID="shift-2026-05-25"
curl -fsS "$EULER_BASE_URL/healthz"
curl -fsS "$EULER_BASE_URL/readyz"

Flow 1: register a third-party MCAP

Create the project, then register the raw MCAP source before Euler walks or mutates any derived artifacts.

curl

curl -fsS -X POST "$EULER_BASE_URL/v1/projects" \
  -H "Authorization: Bearer $EULER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "warehouse-arm",
    "name": "Warehouse Arm"
  }'
 
curl -fsS -X POST "$EULER_BASE_URL/v1/projects/$EULER_PROJECT_ID/sources" \
  -H "Authorization: Bearer $EULER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "shift-2026-05-25",
    "name": "Shift 2026-05-25",
    "description": "Customer MCAP pilot capture",
    "format": "mcap",
    "uri": "s3://customer-robot-logs/shift-2026-05-25.mcap",
    "include_globs": ["*.mcap"],
    "exclude_globs": [],
    "embodiment_hint": "warehouse-arm-v2",
    "project_id": "warehouse-arm",
    "labels": {
      "customer": "acme",
      "site": "floor-7"
    },
    "registered_by": "ml-lead@acme.example",
    "registered_at": "2026-05-26T00:00:00Z",
    "version": 1
  }'

Python

import os
 
from euler_sdk import EulerClient
 
client = EulerClient(os.environ["EULER_BASE_URL"], api_key=os.environ["EULER_API_TOKEN"])
 
client.create_project({"id": "warehouse-arm", "name": "Warehouse Arm"})
client.add_source(
    "warehouse-arm",
    {
        "id": "shift-2026-05-25",
        "name": "Shift 2026-05-25",
        "description": "Customer MCAP pilot capture",
        "format": "mcap",
        "uri": "s3://customer-robot-logs/shift-2026-05-25.mcap",
        "include_globs": ["*.mcap"],
        "exclude_globs": [],
        "embodiment_hint": "warehouse-arm-v2",
        "project_id": "warehouse-arm",
        "labels": {"customer": "acme", "site": "floor-7"},
        "registered_by": "ml-lead@acme.example",
        "registered_at": "2026-05-26T00:00:00Z",
        "version": 1,
    },
)

TypeScript

import { EulerClient } from "@sudotank/euler-sdk";
 
const client = new EulerClient({
  baseUrl: process.env.EULER_BASE_URL!,
  apiKey: process.env.EULER_API_TOKEN!,
});
 
await client.create_project({
  id: "warehouse-arm",
  name: "Warehouse Arm",
});
 
await client.add_source("warehouse-arm", {
  id: "shift-2026-05-25",
  name: "Shift 2026-05-25",
  description: "Customer MCAP pilot capture",
  format: "mcap",
  uri: "s3://customer-robot-logs/shift-2026-05-25.mcap",
  include_globs: ["*.mcap"],
  exclude_globs: [],
  embodiment_hint: "warehouse-arm-v2",
  project_id: "warehouse-arm",
  labels: { customer: "acme", site: "floor-7" },
  registered_by: "ml-lead@acme.example",
  registered_at: "2026-05-26T00:00:00Z",
  version: 1,
});

Flow 2: plan a command-led ingest

Ask Euler for the deterministic plan before execution. Approval checkpoints and per-step evidence stay visible in the hosted UI and API.

curl

curl -fsS -X POST "$EULER_BASE_URL/v1/projects/$EULER_PROJECT_ID/command" \
  -H "Authorization: Bearer $EULER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "command": "ingest the MCAP source, map topics, score readiness, and export accepted episodes",
    "episodes": 120
  }'

Python

plan = client.plan_command(
    "warehouse-arm",
    {
        "command": "ingest the MCAP source, map topics, score readiness, and export accepted episodes",
        "episodes": 120,
    },
)
print(plan["content_hash"])

TypeScript

const plan = await client.plan_command("warehouse-arm", {
  command:
    "ingest the MCAP source, map topics, score readiness, and export accepted episodes",
  episodes: 120,
});
 
console.log(plan);

Flow 3: search, save, and hand off a slice

Hosted /v1 routes expose projects, sources, runs, episodes, exports, and deterministic Ask Euler summaries. Search and saved-slice construction are currently local package primitives and MCP tools, so they can run inside a customer-controlled agent or batch job with no paid API calls.

curl

curl -fsS "$EULER_BASE_URL/v1/projects/$EULER_PROJECT_ID/episodes" \
  -H "Authorization: Bearer $EULER_API_TOKEN"
 
curl -fsS "$EULER_BASE_URL/v1/projects/$EULER_PROJECT_ID/exports" \
  -H "Authorization: Bearer $EULER_API_TOKEN"

Python

from euler.index import EpisodeSearchIndex, SearchQuery, save_slice_definition
 
episodes = load_episode_refs_from_your_euler_export()
 
response = EpisodeSearchIndex(episodes).search(
    SearchQuery(
        text="failed grasp recovery with object slip",
        task="pick-place",
        outcome="failure",
        min_readiness_score=0.55,
    )
)
 
saved = save_slice_definition(
    slice_id="failed-grasp-recovery",
    search_response=response,
    created_by="ml-lead@acme.example",
)
 
eval_set = saved.to_eval_set(locked_by="ml-lead@acme.example")
print(saved.content_hash, eval_set.content_hash)

TypeScript

const episodes = await client.list_episodes("warehouse-arm");
const exports = await client.list_exports("warehouse-arm");
 
console.log({ episodes, exports });

Agent handoff

For MCP-compatible agents, use euler.search_episodes, euler.create_slice, euler.export_slice, euler.verify_receipt, and euler.import_feedback. Private or high-impact exports return an approval-required payload instead of mutating customer data.

from euler.integrations import EulerMcpServer
 
server = EulerMcpServer(episodes)
result = server.call_tool(
    "euler.search_episodes",
    {
        "text": "failed grasp recovery",
        "filters": {"task": "pick-place", "outcome": "failure"},
    },
)
print(result.ok, result.payload["response"]["content_hash"])