Skip to main content

annotators

The Python client for annotators.ai: human review for any model output. Send what your model returned to have it checked, or leave the output out and have the item labeled. A machine check goes first, and people see only what it doubts.

pip install annotators

Python 3.10 or later. The full API reference is at annotators.ai/docs.

Get an API key

Sign up at annotators.ai/console, create a workspace, and make a key under API keys. The client reads it from the environment:

export ANNOTATORS_API_KEY=ak_...

Your first annotation

A task says what an item looks like and which fields to fill. Create one once:

from annotators import Annotators

client = Annotators()  # reads ANNOTATORS_API_KEY

client.tasks.create(
    slug="ticket-triage",
    name="Support ticket triage",
    instructions="Pick the team that should handle the ticket.",
    fields=[
        {"name": "team", "kind": "choice", "options": ["billing", "bug", "account", "other"]},
        {"name": "urgent", "kind": "bool"},
    ],
)

Field kinds are choice, multi_label, bool, score (with levels), extract (a list of strings) and text.

Then send an item, with what your model returned and how sure it was:

a = client.annotate(
    "ticket-triage",
    input={"subject": "Charged twice", "body": "I was billed twice for October."},
    output={"team": "billing", "urgent": False},   # what your model returned
    source={"model": "my-model", "confidence": 0.62},
    metadata={"ticket_id": "T-1042"},              # comes back with the verdict
    idempotency_key="ticket-T-1042",               # retries don't create a second item
)
print(a["id"], a["status"])

At or above the task's accept_threshold (0.9 by default) the output is approved without anyone looking. At 0.62 it goes to people, and you can review it yourself under Review in the console. Wait for the verdict, or have it sent to a webhook (below):

a = client.annotations.wait(a["id"])     # polls; fine for scripts
print(a["verdict"], a["final_output"])   # approved, corrected or rejected

final_output is the answer to use: your output if it was approved, the reviewer's if they corrected it, and None if it was rejected.

Who reviews

Left out, workforce is your own team (private): the members of your console workspace and the reviewers you invite.

r = client.reviewers.invite("sam@example.com", display_name="Sam")   # the token is shown once
client.reviewers.remove(r["id"])                                     # frees their seat

Invited reviewers and members who review in the console share your plan's reviewer seats. Past the limit, invite fails with AnnotatorsError 402.

The annotators.org crowd (workforce="open" or "vetted") is on a waitlist. Join it under Review in the console. Until your workspace has crowd access, asking for the crowd fails with AnnotatorsError 403.

Webhooks

Set a webhook URL under Settings in the console, or pass callback_url= with a call. Each completed annotation or survey is POSTed there, signed with your workspace's signing secret (also under Settings), and retried with backoff until your endpoint answers 2xx. Verify the signature against the raw request body:

from flask import Flask, request
from annotators import WebhookVerificationError, verify

app = Flask(__name__)

@app.post("/annotators")
def annotators_webhook():
    try:
        event = verify(request.get_data(), request.headers.get("Annotators-Signature", ""),
                       WEBHOOK_SECRET)
    except WebhookVerificationError:
        return "", 400
    if event["type"] == "annotation.completed":
        a = event["data"]
        save_triage(a["metadata"]["ticket_id"], a["final_output"], a["verdict"])
    return "", 204

verify rejects a bad signature, and a timestamp more than five minutes off, then returns the parsed event. Retried deliveries keep their event id, so you can skip ones you've seen.

Machine checks

With a confidence in source, overall or per field ("field_confidence": {"urgent": 0.4}), your number decides: at or above accept_threshold the output is approved, below it people review it. Fields you give no confidence for go to people. Without a confidence, our decision model checks the output. Pass check="annotators-judge-1" (with the call or in the task's defaults) to have the decision model check it even when you send a confidence, or check="none" to skip the machine.

mode picks who looks: "auto" (the default; machine first, people only if doubtful), "human" (always people), "machine" (never people) or "sample" (people review a sample_rate share).

No model of your own

Leave output out and the item is labeled for you, from the task's examples and any you pass with the call:

a = client.annotate(
    "ticket-triage",
    input={"subject": "Can't log in", "body": "Password reset email never arrives."},
    examples=[{"input": past.input, "output": past.output}],
    mode="machine",            # never people: doubtful results come back as low_confidence
)
team, confidence = a["final_output"], a["agreement"]

Surveys

Ask a number of people for their reaction to a message, headline or document (a task with kind="survey"):

s = client.surveys.create("message-reaction", input={"message": draft}, n_responses=50)

Errors and settings

API errors raise AnnotatorsError, with the HTTP status and the API's detail.

Annotators(api_key="ak_...", base_url="https://api.annotators.ai", timeout=30)

Both default to the environment: ANNOTATORS_API_KEY and ANNOTATORS_BASE_URL. The client is a context manager (with Annotators() as client:) and closes its HTTP connection on exit.

Metadata

Release files for annotators 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for annotators 0.1.0
File Size Uploaded Provenance
annotators-0.1.0.tar.gz 9.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for annotators 0.1.0
File Interpreter ABI Platform
annotators-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 18.1 kB

Release files / annotators-0.1.0.tar.gz

Download URL annotators-0.1.0.tar.gz
Size 9.3 kB
Tags Source
SHA-256 checksum
How to use checksums
f5bd20477616b971324bd2df894b9dca5f399a9f1762fa9ea663a4ed310a27b5
BLAKE2b-256 checksum
How to use checksums
d8be80fea9a597c8552e98b532a29540fa8d56ddab0b6c3f5c1fcadd7f60b4c7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.7

Release files / annotators-0.1.0-py3-none-any.whl

Download URL annotators-0.1.0-py3-none-any.whl
Size 8.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fdf2967b9dff7d34ba824f00de7f7e254d872d8db8d75dea562ed60b107d144a
BLAKE2b-256 checksum
How to use checksums
0e8ed0efb389482fa006bf1198847c65e3a1fb9971bb1927ef3053231bcb1ed1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.7

Security for annotators 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page