Skip to main content

Official Python SDK for the Delega API

Project description

Delega Python SDK

Official Python SDK for the Delega API.

Installation

pip install delega

For async support:

pip install 'delega[async]'

Quick Start

from delega import Delega

client = Delega(api_key="dlg_...")

# List tasks
tasks = client.tasks.list()

# Create a task
task = client.tasks.create("Deploy to production", priority=1, labels=["ops"])

# Complete a task
client.tasks.complete(task.id)

Authentication

Pass your API key directly or set the DELEGA_API_KEY environment variable:

# Explicit
client = Delega(api_key="dlg_...")

# From environment
# export DELEGA_API_KEY=dlg_...
client = Delega()

To target a custom endpoint (advanced), point base_url at the API namespace:

client = Delega(api_key="dlg_...", base_url="http://localhost:18890")
# or: Delega(api_key="dlg_...", base_url="https://delega.yourcompany.com/api")

Passing a bare localhost URL defaults to the /api namespace. For remote custom endpoints, include /api explicitly.

Tasks

# List with filters
tasks = client.tasks.list(priority=1, completed=False)
tasks = client.tasks.list(labels=["urgent"], due_before="2026-12-31")

# Search
tasks = client.tasks.search("deploy")

# CRUD
task = client.tasks.create("Fix bug", description="Crash on login", priority=1)
task = client.tasks.get("task_id")
task = client.tasks.update("task_id", content="Updated title", priority=3)
client.tasks.delete("task_id")

# Completion
client.tasks.complete("task_id")
client.tasks.uncomplete("task_id")

# Delegation
subtask = client.tasks.delegate("parent_task_id", "Research options", priority=2)

# Comments
client.tasks.add_comment("task_id", "Looks good, shipping it")
comments = client.tasks.list_comments("task_id")

Claiming (work queues)

Worker agents can pull tasks from a shared queue with claim(). Claims are atomic (no two workers get the same task) and ordered by priority, then creation time. A claim holds a lease — extend it with heartbeat() while you work, release it with release() if you can't finish, or complete() the task when done:

import time

while True:
    task = client.tasks.claim(labels=["worker"], lease_seconds=300)
    if task is None:
        time.sleep(10)  # queue empty — back off (or break)
        continue

    try:
        # ... do the work, periodically extending the lease:
        client.tasks.heartbeat(task.id, lease_seconds=300)
        # ...
        client.tasks.complete(task.id)
    except Exception:
        client.tasks.release(task.id)  # hand it back to the queue
        raise

claim() returns None when no claimable task is available. lease_seconds accepts 30-3600 (default 300); if the lease expires without a heartbeat, the task becomes claimable again. Claiming sets status to "claimed" but never touches assigned_to_agent_id. Filter claimed/unclaimed tasks with client.tasks.list(claimed=True) or claimed=False.

Session State

Report what a worker is doing on a task — without touching the claim lease — so orchestrators and dashboards can see working, waiting_input, or errored states:

client.tasks.set_state(task.id, "waiting_input", detail="Need repo credentials")

Task Context & Provenance

Each task carries a persistent context blob shared across sessions and agents. Writes merge (existing keys are preserved) and every write is recorded in an append-only provenance ledger:

# Read the current context and its version
snap = client.tasks.get_context(task.id, include_provenance=True)
print(snap.context, snap.version, snap.provenance)

# Merge keys, attributing the write and guarding against concurrent writers
client.tasks.update_context(
    task.id,
    {"decision": "use Postgres", "files": ["db.py"]},
    source="agent_observed",        # human_stated | agent_inferred | agent_observed | imported
    expected_version=snap.version,  # raises a 409 DelegaAPIError on conflict
)

# Audit who wrote what, when
history = client.tasks.context_history(task.id, key="decision")
for entry in history.entries:
    print(entry.version, entry.author_name, entry.source, entry.value)

# Mark a live entry as stale without changing the value
client.tasks.supersede_context(task.id, "decision")

Task Links

Attach repo activity or URLs to a task (the hosted GitHub integration creates these automatically from delega:#<task-id> mentions):

link = client.tasks.add_link(task.id, "pr", "42", repo="acme/webapp")
links = client.tasks.list_links(task.id)
client.tasks.delete_link(task.id, link.id)

Agents

agents = client.agents.list()
agent = client.agents.create("deploy-bot", display_name="Deploy Bot")
print(agent.api_key)  # Only available at creation time

# Role presets (admin key required): worker (own-task scope, default),
# coordinator (sees + can comment on all account tasks), admin
scrum = client.agents.create("scrum-bot", role="coordinator")
client.agents.set_role(agent.id, "coordinator")
print(agent.role)

client.agents.update(agent.id, description="Handles deployments")
result = client.agents.rotate_key(agent.id)
print(result["api_key"])

client.agents.delete(agent.id)

Projects

projects = client.projects.list()
project = client.projects.create("Backend", emoji="⚙️", color="#3498db")

Webhooks

webhooks = client.webhooks.list()
webhook = client.webhooks.create(
    "https://example.com/webhook",
    events=["task.created", "task.completed"],
    secret="whsec_...",
)

Account

me = client.me()       # Get authenticated agent info
usage = client.usage()  # Get API usage stats

me() and usage() are hosted-account endpoints (api.delega.dev). Custom /api-namespace endpoints expose task/agent/project/webhook APIs, but may not implement those hosted account endpoints.

Async Client

from delega import AsyncDelega

async with AsyncDelega(api_key="dlg_...") as client:
    tasks = await client.tasks.list()
    task = await client.tasks.create("Async task")
    await client.tasks.complete(task.id)

The async client has the same interface as the sync client, but all methods are coroutines. Requires httpx (pip install 'delega[async]').

Error Handling

from delega import DelegaError, DelegaAPIError, DelegaAuthError, DelegaNotFoundError, DelegaRateLimitError

try:
    task = client.tasks.get("nonexistent")
except DelegaNotFoundError:
    print("Task not found")
except DelegaAuthError:
    print("Invalid API key")
except DelegaRateLimitError:
    print("Too many requests")
except DelegaAPIError as e:
    print(f"API error {e.status_code}: {e.error_message}")
except DelegaError as e:
    print(f"SDK error: {e}")

Models

All resource methods return typed dataclasses:

  • Task - id, content, description, priority, labels, due_date, completed, project_id, parent_id, claimed_by_agent_id, claimed_at, lease_expires_at, session_state, session_state_detail, accountable_agent_id, context_version, created_at, updated_at

The claiming fields (claimed_by_agent_id, claimed_at, lease_expires_at) are set while a task is claimed via tasks.claim() and are None otherwise. A claimed task has status == "claimed".

  • TaskLink - id, task_id, kind (branch/commit/pr/url), repo, ref, url, created_by_agent_id, created_at
  • ContextSnapshot - context, version, provenance (from tasks.get_context())
  • ContextEntry / ContextHistory - the provenance ledger (from tasks.context_history() / tasks.supersede_context())
  • Comment - id, task_id, content, created_at
  • Agent - id, name, display_name, description, api_key, created_at, updated_at

The api_key field is returned on agent creation and key rotation responses, but it is hidden from the default dataclass repr() to reduce accidental secret leakage in logs.

  • Project - id, name, emoji, color, created_at, updated_at

License

MIT

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

delega-0.5.0.tar.gz (27.5 kB view details)

Uploaded Source

Built Distribution

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

delega-0.5.0-py3-none-any.whl (23.7 kB view details)

Uploaded Python 3

File details

Details for the file delega-0.5.0.tar.gz.

File metadata

  • Download URL: delega-0.5.0.tar.gz
  • Upload date:
  • Size: 27.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for delega-0.5.0.tar.gz
Algorithm Hash digest
SHA256 cd1f6d24cf4613b53e006f98a394f8f20423765861f0decdc871c3574693152a
MD5 de756090ae046170dea1ff3de9a6aa24
BLAKE2b-256 142d68f11adab09acdad5f35d4738e71ab65f23d9a045dffe13e1c45521d66e3

See more details on using hashes here.

Provenance

The following attestation bundles were made for delega-0.5.0.tar.gz:

Publisher: publish.yml on delega-dev/delega-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file delega-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: delega-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 23.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for delega-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e2601034185066710920bce3694bb1217f59d745b319f725e0ac1225036f1455
MD5 b0a43ba4711b0e2935d6d294f9961ddc
BLAKE2b-256 c394fe9f0363b4658cc02f057a0673991cee5ff296a97e4ca2f6687815250caf

See more details on using hashes here.

Provenance

The following attestation bundles were made for delega-0.5.0-py3-none-any.whl:

Publisher: publish.yml on delega-dev/delega-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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