Skip to main content

A Python SDK for interacting with the ChirrOp API.

Project description

ChirrOp SDK

The ChirrOp SDK for Python sends OpenClaw-friendly flat events to ChirrOp/Ingres with batching and retries.

Installation

pip install chirrop

Quick Start

Global API

from chirrop import ChirrOp, Log

ChirrOp.initialize(api_key="chp_your_api_key")
ChirrOp.log_event(Log(log_id="9f97d65f-fb30-4062-b4d0-8617c03fe4f6", event="tool.errors.count", value=1, agent="openclaw.main", meta={"tool_name": "browser.open"}))
ChirrOp.flush()
ChirrOp.stop()

Instance API (Recommended)

from chirrop import new_client, Log

client = new_client(api_key="chp_your_api_key")
client.log(Log(event="task.duration_ms", value=420, agent="openclaw.main", meta={"task_name": "email_triage"}))
client.flush()

events = client.list_events()
task_duration = next(
    (event_def for event_def in events if event_def.get("agent") == "openclaw.main" and event_def.get("event") == "task.duration_ms"),
    None,
)

if task_duration:
    analytics = client.get_event_analytics(
        task_duration["event_id"],
        view="window",
        period="1h",
        previous="previous_window",
    )

client.close()

API

Config

Config fields:

  • api_key (str, optional): API key. Must start with chp_.
  • api_endpoint (str, optional): Full ingestion endpoint override.
  • servicer_endpoint (str, optional): Control-plane endpoint override. Defaults to https://api.chirrop.com/v1.0.
  • retries (int, optional): Retry attempts.
  • timeout (float, optional): HTTP timeout in seconds.
  • batch_size (int, optional): Flush threshold.
  • flush_delay (float, optional): Worker flush interval in seconds.
  • queue_size (int, optional): In-memory queue capacity. 0 means unbounded and is the default.
  • log_level (int, optional): Python logging level.

API key resolution precedence when api_key is omitted:

  1. api_key passed in Config/initialize
  2. CHIRROP_API_KEY process environment variable
  3. CHIRROP_API_KEY in local .env

Default ingest endpoint: https://logs.chirrop.com/v1.0/logs. Default servicer endpoint: https://api.chirrop.com/v1.0. The same bearer token is used for both ingest and servicer APIs. Queued logs are not dropped locally because of queue capacity or retry exhaustion.

Retry behavior

The SDK retries network/transport failures, 429 responses, and retryable 5xx responses such as 502 and 504. It does not retry 401, 403, 404, 500, or 503, and 401/403 errors surface the ChirrOp response message when available.

Important: When all retry attempts are exhausted, logs are silently dropped. The SDK is designed to never block your application — if the ChirrOp API is persistently unreachable, queued logs will be discarded rather than causing backpressure. Monitor your ChirrOp dashboard to ensure logs are arriving as expected.

Log

Log fields:

  • agent (str, optional): Free-form agent identifier text.
  • log_id (str, optional): UUID idempotency key for the log. Generated automatically when omitted.
  • event (str, required): Event name.
  • value (number, required): Numeric value.
  • occurred_at (datetime | str, optional): Event occurrence timestamp.
  • meta (json, optional): Additional JSON-encodable metadata.

Example with occurred_at:

from datetime import datetime, timezone

entry = Log(
    agent="openclaw.main",
    event="tokens.used",
    value=1530,
    occurred_at=datetime(2026, 3, 5, 14, 30, 0, tzinfo=timezone.utc),
)

Notes:

  • agent whitespace-only values are treated as omitted.
  • log_id blank values are treated as omitted and replaced with a generated UUIDv4.
  • event must be non-empty after trimming.
  • occurred_at must be within the last 30 days and no more than 1 day in the future.
  • Use timezone-aware UTC datetimes or ISO8601 UTC strings, for example 2026-03-05T14:30:00Z.
  • meta must be JSON-encodable.
  • Unknown events are auto-created in Ingres as event definitions.

Event definition helpers

events = client.list_events()
created = client.create_event({"event": "tool.errors.count"})
event_def = client.get_event(events[0]["event_id"])
updated = client.update_event(event_def["event_id"], {
    "description": "OpenClaw Tool Errors",
})

analytics = client.get_event_analytics(
    event_def["event_id"],
    view="window",
    period="1h",
    previous="previous_window",
)

Policy and alert helpers

policies = client.list_policies()
policy = client.get_policy("pol_123")
updated_policy = client.update_policy("pol_123", {"title": "Updated"})
policy = client.create_policy({
    "event_id": "evt_123",
    "title": "OpenClaw tool errors spike",
    "condition": "gt",
    "threshold": 5,
    "period": "hour",
    "aggregate": "sum",
    "enabled": True,
})
alerts = client.list_alerts("triggered")
alert = client.get_alert(alerts[0]["alert_id"])
deliveries = client.get_alert_deliveries(alerts[0]["alert_id"], limit=20, offset=0, kind="alert")
rollups = client.get_event_logs("evt_123", period="hour", limit=25, offset=0)
ack = client.acknowledge_alert(alerts[0]["alert_id"])
resolved = client.resolve_alert(ack["alert_id"])
archived = client.archive_alert(resolved["alert_id"])
test_result = client.test_destination("whk_123")
deliveries = client.get_alert_deliveries(test_result["alert_id"], kind="test")

destination = client.create_destination(
    {
        "channel": "slack",
        "url": "https://hooks.slack.com/services/T000/B000/secret",
        "scope": "all",
        "policy_ids": [],
        "enabled": True,
    }
)
details = client.get_destination(destination["destination_id"])
updated_destination = client.update_destination(destination["destination_id"], {"enabled": False})

Convenience constructor

Use new_client(...) to create standalone clients without manually constructing Config.

Destination Setup Examples

Create a Slack destination for OpenClaw alerts:

import requests

requests.post(
    "https://api.chirrop.com/v1.0/destinations",
    json={
        "url": "https://hooks.slack.com/services/T000/B000/secret",
        "channel": "slack",
        "scope": "all",
        "policy_ids": [],
        "enabled": True,
    },
    headers={"Authorization": f"Bearer {api_key}"},
    timeout=10,
)

destination = client.create_destination({"channel": "slack", "scope": "all", "enabled": True})
details = client.get_destination(destination["destination_id"])
updated_destination = client.update_destination(destination["destination_id"], {"enabled": False})

Create a Telegram destination for OpenClaw alerts:

requests.post(
    "https://api.chirrop.com/v1.0/destinations",
    json={
        "channel": "telegram",
        "enabled": True,
        "scope": "all",
        "policy_ids": [],
        "credentials": {
            "bot_token": "123456:telegram-bot-token",
            "chat_id": "987654321",
        },
    },
    headers={"Authorization": f"Bearer {api_key}"},
    timeout=10,
)

Send a test notification:

test_result = client.test_destination("whk_123")
client.get_alert_deliveries(test_result["alert_id"], kind="test")

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

chirrop-0.1.0.tar.gz (11.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

chirrop-0.1.0-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

Details for the file chirrop-0.1.0.tar.gz.

File metadata

  • Download URL: chirrop-0.1.0.tar.gz
  • Upload date:
  • Size: 11.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.11.3

File hashes

Hashes for chirrop-0.1.0.tar.gz
Algorithm Hash digest
SHA256 39b310f92fa7951295358bbc029c83529515a6d381d83aa940e0b1efec713a51
MD5 a4788c88b0c5ac6d06acc492bd1fc65c
BLAKE2b-256 f55b9470e2426882b898bffc5da523549bcdb6499509c3210d8bb5217dcd4e36

See more details on using hashes here.

File details

Details for the file chirrop-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: chirrop-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.11.3

File hashes

Hashes for chirrop-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 eedf916e6be65c88e98b7b35382ed3b4b8afb2173be6fe07ee472b79d0b0a1bb
MD5 0cf22a7f2cabfd8935b9d3df6d5238e5
BLAKE2b-256 4e75d3813a5b836461f7a1622f0a81231a658e47985114b970f067b5f7a639e4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page