Lovelace Developer Portal
Overview
Auth Hub
Studio
Agents Cloud
Skills
Memory Platform
Lattice Cloud
Hosting
Ada CLI
MCP Gateway
Ada
Periscope
Editor Extensions
Skip to main content

Skills Quickstart

This guide takes a server-side developer from API key to a completed skill invocation. The examples use placeholder input and public-safe identifiers only. Keep API keys in your secret manager, shell profile, or deployment environment, and call the Skills API from a trusted server boundary.

Base URL: https://agents.uselovelace.com

Required scopes:

ScopeUsed for
skills:readBrowse reusable skills, inspect generation jobs, list versions, and poll invocation status.
skills:writeCreate a generation job when the library cannot satisfy the request.
skills:executeInvoke the selected skill version.

1. Start From An API Key

Create a developer API key from API keys with the scopes above. A developer key has the sk_live_ prefix. The commands below expect the key to be available as LOVELACE_API_KEY.

Send the key in the x-api-key header on every Skills request:

bash
-H "x-api-key: $LOVELACE_API_KEY"

The Authorization: Bearer header is reserved for short-lived JWT session tokens. A developer API key is not a JWT — sending it as a bearer token fails authentication. Use x-api-key for the sk_live_ key.

Do not paste real keys into source files, shell history, issue comments, support tickets, or generated examples.

2. Preflight Reuse Before Generation

Ask the library whether an approved visible skill can satisfy the capability before creating a generation job.

bash
curl -sS https://agents.uselovelace.com/api/v1/tool-generation-jobs/preflight \
  -H "x-api-key: $LOVELACE_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
    "description": "Normalize invoice CSV rows into accounting import records",
    "capabilities": ["csv_normalization", "accounting_import"],
    "category": "business_operations",
    "billingMode": "private_generation",
    "inputSchema": {
      "type": "object",
      "properties": {
        "csvText": { "type": "string" }
      },
      "required": ["csvText"]
    },
    "outputSchema": {
      "type": "object",
      "properties": {
        "records": { "type": "array" }
      },
      "required": ["records"]
    }
  }'

If the response has state: "reuse" and includes matchedSkill, use matchedSkill.autoToolId and matchedSkill.defaultVersionId for invocation. If the response has state: "recommend", show the recommendation to the user or operator before spending generation quota. If the response has state: "synthesize", continue to generation.

3. Create A Generation Job When Reuse Does Not Fit

bash
curl -sS https://agents.uselovelace.com/api/v1/tool-generation-jobs \
  -H "x-api-key: $LOVELACE_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
    "description": "Normalize invoice CSV rows into accounting import records",
    "capabilities": ["csv_normalization", "accounting_import"],
    "category": "business_operations",
    "billingMode": "private_generation",
    "permissions": {},
    "inputSchema": {
      "type": "object",
      "properties": {
        "csvText": { "type": "string" }
      },
      "required": ["csvText"]
    },
    "outputSchema": {
      "type": "object",
      "properties": {
        "records": { "type": "array" }
      },
      "required": ["records"]
    }
  }'

The accepted response includes:

json
{
  "id": "job_123",
  "status": "queued",
  "statusUrl": "/api/v1/tool-generation-jobs/job_123",
  "pricingPreview": {
    "billingMode": "private_generation",
    "unitMetric": "skill_generations"
  }
}

4. Poll The Job With A Bound

Poll statusUrl until the job is ready, failed, or canceled. Use a bounded loop, backoff, and a timeout in your worker instead of an unbounded client-side interval.

bash
curl -sS https://agents.uselovelace.com/api/v1/tool-generation-jobs/job_123 \
  -H "x-api-key: $LOVELACE_API_KEY"

A ready job includes toolId, versionId, and toolUrl:

json
{
  "id": "job_123",
  "toolId": "tool_invoice_normalizer",
  "versionId": "ver_20260614",
  "status": "ready",
  "toolUrl": "/api/v1/tools/tool_invoice_normalizer"
}

If the job fails, handle failureCategory and failureMessage as public-safe diagnostics. Do not log prompts, generated source, validation payloads, or private customer records.

5. Select A Validated Version

List versions and pick a validated selectable version. Use latest_selectable for normal traffic and pinned_selectable when you need a stable retained version.

bash
curl -sS "https://agents.uselovelace.com/api/v1/tools/tool_invoice_normalizer/versions?limit=25&offset=0" \
  -H "x-api-key: $LOVELACE_API_KEY"

Use the version string in the invocation request when you want to pin a specific version. Omit version to use the current latest selectable version.

6. Invoke The Skill

bash
curl -sS https://agents.uselovelace.com/api/v1/tool-invocations \
  -H "x-api-key: $LOVELACE_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
    "toolId": "tool_invoice_normalizer",
    "version": "1.0.0",
    "input": {
      "csvText": "invoice_id,total,currency\nINV-100,42.00,USD"
    },
    "metadata": {
      "requestKind": "quickstart_example"
    }
  }'

The response includes an invocation status URL:

json
{
  "invocationId": "inv_123",
  "toolId": "tool_invoice_normalizer",
  "status": "pending",
  "statusUrl": "/api/v1/tool-invocations/inv_123"
}

Poll or long-poll the invocation with a timeout:

bash
curl -sS "https://agents.uselovelace.com/api/v1/tool-invocations/inv_123/wait?timeoutMs=5000" \
  -H "x-api-key: $LOVELACE_API_KEY"

Completed invocations return status: "completed" and an output object. Failed invocations return status: "failed", failureCategory, and a safe failureMessage.

7. Handle Typed Failures

Branch on error and details.category, not on message text.

ts
type SkillsErrorBody = {
  readonly error: string;
  readonly details?: {
    readonly category?: string;
    readonly retryable?: boolean;
    readonly dimension?: string;
    readonly current?: number;
    readonly limit?: number;
  };
};

function shouldRetrySkillsRequest(error: SkillsErrorBody): boolean {
  return error.details?.retryable === true;
}

function describeSkillsFailure(error: SkillsErrorBody): string {
  switch (error.error) {
    case "authorization_failed":
      return "The request is not authorized for this Skills operation.";
    case "invalid_request":
      return "The request shape is invalid.";
    case "quota_exceeded":
      return `Quota exhausted for ${error.details?.dimension ?? "Skills"}.`;
    case "credit_pending":
      return "A reusable-skill credit is pending settlement.";
    case "billing_required":
      return "The account owner needs to resolve billing.";
    case "billing_unavailable":
      return "Billing state is temporarily unavailable.";
    case "learning_consent_required":
      return "Learning-enabled generation needs account consent.";
    case "unavailable_version":
      return "The requested skill version is unavailable.";
    case "validation_error":
      return "The candidate failed validation.";
    case "execution_failed":
      return "The protected execution boundary failed.";
    default:
      return "The Skills request failed with a typed public error.";
  }
}

Use bounded retries only when details.retryable is true. See troubleshooting for action guidance and billing for quota and credit behavior.

Build and deploy AI agents with ease.

Quick Start

  • Getting Started
  • Build Your First Agent
  • Platform Concepts
  • Examples & Tutorials

Develop

  • Create an Agent
  • Connect an MCP Server
  • API Reference
  • CLI Tools

Platform

  • Agents Cloud
  • Roadmap
  • Platform Changelog
  • Status

Resources

  • Discord
  • GitHub
  • Support
  • Developer Blog
Lovelace logo
Lovelace
Made with ❤️ by Reasonable Tech CompanySupport
TermsPrivacy
All systems operational

Library

Generate

Overview

Quick Start

Billing & Quotas

Troubleshooting

API Reference