Valar

API Documentation

Connect your agents to Valar

Getting Started

The Valar API lets you register agents, log events, track inter-agent messages, collect feedback, and monitor usage. Any agent you build — regardless of language or framework — can connect by making standard HTTP requests.

Quick start in 3 steps

  1. Get your API key — set API_KEY in your .env file and pass it as the X-API-Key header with every request.
  2. Register your agent — POST to /agents with a name and type.
  3. Start logging events — POST to /events each time something noteworthy happens.
bash
# 1. Register your agent
curl -X POST https://valar.click/api/agents \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-agent",
    "type": "assistant",
    "icon": "🤖",
    "platform": "python"
  }'

# 2. Log an event (use the agent id from step 1)
curl -X POST https://valar.click/api/events \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "<agent-uuid>",
    "event_type": "task_completed",
    "source": "agent_core",
    "level": "info",
    "payload": {"task": "summarize_meeting"}
  }'

Authentication

All endpoints except /health require the X-API-Key header. Requests without a valid key receive 401 Unauthorized.

http
GET /agents HTTP/1.1
Host: localhost:8100
X-API-Key: your-api-key-here

Generating a key

bash
openssl rand -hex 32

Add the generated value as API_KEY in your .env file. The same key must be sent by every client connecting to the API.

Rate limiting

The API enforces a default rate limit of 100 requests per minute per IP. Exceeding this returns 429 Too Many Requests.

Agents

Register, list, update, and manage your agents. Each agent has a unique name, type, status, and optional metadata.

Events

Events are the primary telemetry primitive. Every meaningful action your agent performs should be logged as an event.

Event fields

  • event_type — what happened (e.g. task_completed, api_call)
  • source — which subsystem emitted it (e.g. scheduler, slack)
  • level info | warning | error | critical
  • trace_id — flat correlation ID across related events
  • parent_event_id — hierarchical linking for sub-tasks
  • payload — arbitrary JSON with extra context

Agent Messages

Log and query inter-agent communication. Useful for tracing how agents collaborate on tasks.

Feedback

Collect user feedback on agents, events, or messages. Feedback powers the satisfaction metrics on the dashboard.

Usage & Costs

Record and query token usage, API call counts, latency, and cost metrics per agent. The server automatically computes dollar costs from token counts using built-in model pricing.

Reporting usage after every LLM call

For accurate cost tracking, your agent must call POST /usage after each LLM API call. Extract token counts from the LLM response and post them — the server computes computed_cost automatically from the model name and token counts. You can pass cost: 0 if you don't know the client-side cost.

bash
# Report usage after an Anthropic API call
curl -X POST https://valar.click/api/usage \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "<your-agent-uuid>",
    "model": "claude-sonnet-4-20250514",
    "tokens_input": 1500,
    "tokens_output": 800,
    "cached_tokens": 200,
    "cost": 0.0,
    "api_calls": 1,
    "avg_latency_ms": 1200,
    "provider": "anthropic"
  }'
python
# Python example — after each Anthropic call
response = await anthropic_client.messages.create(...)

await valar_client._request("POST", "/usage", json={
    "agent_id": str(agent.id),
    "model": response.model,
    "tokens_input": response.usage.input_tokens,
    "tokens_output": response.usage.output_tokens,
    "cached_tokens": getattr(response.usage, "cache_read_input_tokens", 0) or 0,
    "cost": 0.0,
    "api_calls": 1,
    "avg_latency_ms": latency_ms,
    "provider": "anthropic",
})

Tip: The SDK does not yet have a built-in report_usage() method. Use the raw HTTP call above, or add a helper that wraps your LLM client to auto-report after each call.

Skill Marketplace

The Skill Marketplace lets agents submit their capabilities as structured skills. Users approve or deny publication, and anyone can browse approved skills and copy an install prompt to add the skill to another agent.

Workflow

  1. Agent ingests skills — POST to /skills/ingest with a structured breakdown of capabilities.
  2. User reviews — Connected agent owners approve or deny skills in the review queue.
  3. Marketplace — Approved skills appear in the marketplace for anyone to browse and copy.

Ingest payload

Minimum required fields per skill: key, name, category. Rate limit: 50 skills/agent/hour.

json
{
  "agent_id": "<agent-uuid>",
  "skills": [
    {
      "key": "send-slack-dm",
      "name": "Send Slack DM",
      "summary": "Send a direct message via Slack",
      "description_md": "## Overview\n...",
      "category": "messaging",
      "tags": ["slack", "notification"],
      "requirements": [
        {"name": "Slack Bot Token", "type": "credential"}
      ],
      "prompt_template": "To send a Slack DM, use...",
      "code_snippet": "async def send_slack_dm(user, msg): ...",
      "config_schema": {"type": "object", "properties": {}},
      "version": "1.0.0"
    }
  ]
}

Ingest

Review (connected agents only)

Marketplace (approved skills)

Agent Links

Legacy

Python SDK

The project includes a Python SDK (in the sdk/ directory) for async agent integration. It wraps every API endpoint with type-safe methods, automatic retries, and idempotent agent registration.

Installation

bash
# From your agent project, install the SDK dependencies
pip install httpx pydantic

Then copy or symlink the sdk/ directory into your project, or add it to your Python path.

Basic usage

python
from sdk import AgentManagementClient

async with AgentManagementClient(
    base_url="https://valar.click/api",
    api_key="your-api-key",
) as client:
    # Register (idempotent — returns existing agent on conflict)
    agent = await client.register_agent(
        "my-bot",
        type="assistant",
        icon="🤖",
        platform="python",
        description="My first agent",
    )

    # Log events
    await client.log_event(
        agent.id,
        "task_started",
        source="scheduler",
        payload={"job": "daily_report"},
    )

    # Fire-and-forget (non-blocking, errors suppressed)
    client.log_event_fire_and_forget(
        agent.id,
        "heartbeat",
        source="health_check",
    )

    # Batch events
    await client.log_events_batch([
        {"agent_id": str(agent.id), "event_type": "step_1", "level": "info"},
        {"agent_id": str(agent.id), "event_type": "step_2", "level": "info"},
    ])

    # Inter-agent messaging
    other = await client.register_agent("summarizer", type="analyst", icon="📊", platform="python")
    await client.send_message(
        agent.id,
        other.id,
        "request",
        payload={"task": "summarize"},
    )

    # Feedback
    await client.submit_feedback(
        "agent", str(agent.id), "thumbs_up", rating=5,
    )

    # Cleanup old events
    result = await client.cleanup_events(30, agent_name="my-bot")
    print(f"Deleted {result.deleted} old events")

Error handling

python
from sdk.exceptions import (
    AgentManagementError,  # Base exception
    AuthenticationError,   # 401
    NotFoundError,         # 404
    ConflictError,         # 409 (duplicate agent name)
    ValidationError,       # 422
    ServerError,           # 5xx
)

try:
    agent = await client.register_agent("my-bot", ...)
except ConflictError:
    # Agent already exists — register_agent handles this
    # automatically, but you can catch it if needed
    pass
except AuthenticationError:
    print("Check your API key")
except AgentManagementError as e:
    print(f"API error: {e}")

SDK methods reference

MethodDescription
register_agent()Register or get existing agent
list_agents()List agents with filters
get_agent()Get agent by ID
update_agent()Update agent fields
delete_agent()Delete agent
log_event()Log a single event
log_event_fire_and_forget()Non-blocking event log
log_events_batch()Log up to 500 events
list_events()Query events with filters
cleanup_events()Delete old events
send_message()Log inter-agent message
list_messages()Query messages
submit_feedback()Submit feedback
list_feedback()Query feedback
health()Health check (no auth)