Skip to main content

Primitif Python SDK — Mail and Approval APIs for AI agents

Project description

primitif

Python SDK for Primitif — give your AI agents email and human approval.

pip install primitif

Setup

Set your API key as an env var and you're good to go:

export PRIMITIF_API_KEY="pk_live_..."

Mail

Create a temporary mailbox, send and receive emails, then throw it away.

from primitif import Primitif

with Primitif() as p:
    mb = p.mail.create_mailbox(name="support-agent", ttl=3600)
    print(mb.address)  # support-agent-x7k2@mail.primitif.ai

    # send an email
    mb.send(to="user@example.com", subject="Hey", body_text="Following up on your ticket.")

    # check inbox
    for msg in mb.inbox():
        email = mb.read(msg.id)
        print(email.from_address, email.subject, email.body_text)
        # reply to it
        mb.reply(msg.id, body_text="Thanks, we're on it.")

    # done — delete the mailbox
    mb.delete()

If you already have a mailbox token, use it directly:

from primitif import Mailbox

with Mailbox(token="mb_tok_...") as mb:
    mb.send(to="someone@example.com", subject="Hi", body_text="Hello")

Tokens can be persisted for crash recovery:

mb = p.mail.create_mailbox(name="agent")
save_to_db(mb.token)  # persist the token

# later, reconnect:
mb = Mailbox(token=load_from_db())

Send with human approval

Emails can be held for human approval before sending:

result = mb.send(
    to="ceo@bigclient.com",
    subject="Contract proposal",
    body_text="Please find attached...",
    require_approval=True,
)
print(result.status)        # "held"
print(result.approval_url)  # link for a human to approve/reject

Pagination

All list methods return a PaginatedList that you can iterate directly, or use auto_paging_iter() to fetch all pages automatically:

for msg in mb.inbox().auto_paging_iter():
    print(msg.subject)

Approval

Gate your agent's tools behind human approval.

from primitif import Primitif

p = Primitif()

# Protect sensitive tools with a decorator
@p.approval.require_approval()
def send_invoice(client, amount):
    billing.send(client, amount)

@p.approval.require_approval()
def delete_account(user_id):
    accounts.delete(user_id)

# Agent calls the tool — gets a pending approval, carries on
result = send_invoice("Acme", 45000)
print(result.status)        # "pending"
print(result.approval_url)  # human reviews here

Without the decorator:

request = p.approval.create_request(
    action="Delete user account #1234",
    context={"user_id": 1234, "reason": "requested by user"},
    callback_url="https://myapp.com/webhooks/approval",
)

Webhooks

When the human approves, dispatch() automatically executes the right tool with the original arguments:

from flask import Flask, request
from primitif import Primitif, verify_webhook, InvalidSignature

app = Flask(__name__)
p = Primitif()

WEBHOOK_SECRET = "whsec_..."

@p.approval.require_approval()
def send_invoice(client, amount):
    billing.send(client, amount)

@app.post("/webhooks/approval")
def handle_approval():
    try:
        event = verify_webhook(
            secret=WEBHOOK_SECRET,
            signature=request.headers["X-Webhook-Signature"],
            timestamp=request.headers["X-Webhook-Timestamp"],
            body=request.data,
        )
    except InvalidSignature:
        return "", 401

    p.approval.dispatch(event)
    return "", 200

Set your webhook URL in the Console under Settings → Webhooks.

Error handling

All errors inherit from PrimitifError, so you can catch broadly or narrowly:

from primitif import PrimitifError, AuthError, NetworkError
from primitif.mail import MailRateLimitError

try:
    mb.send(to="user@test.com", subject="Hi", body_text="Hello")
except MailRateLimitError as e:
    print(f"Slow down — retry after {e.retry_after}s")
except NetworkError:
    print("Network issue — timeout or DNS failure")
except AuthError:
    print("Bad credentials")
except PrimitifError:
    print("Something went wrong")

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

primitif-0.0.6.tar.gz (20.6 kB view details)

Uploaded Source

Built Distribution

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

primitif-0.0.6-py3-none-any.whl (22.9 kB view details)

Uploaded Python 3

File details

Details for the file primitif-0.0.6.tar.gz.

File metadata

  • Download URL: primitif-0.0.6.tar.gz
  • Upload date:
  • Size: 20.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for primitif-0.0.6.tar.gz
Algorithm Hash digest
SHA256 2d34c989b61463990d0c11cb3716686171cd6c0ae8523324eeb5cf60fda8215a
MD5 bab9873b0c7406e8a6c463ea8c82c959
BLAKE2b-256 855778db65e9781a7a1a570494c142120839afd3f8206060cd7954620616c1e4

See more details on using hashes here.

File details

Details for the file primitif-0.0.6-py3-none-any.whl.

File metadata

  • Download URL: primitif-0.0.6-py3-none-any.whl
  • Upload date:
  • Size: 22.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for primitif-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 a0380ce135da92ff66a630f08cb29233eb97d8fa0f4a421fd49d527714d47bb5
MD5 afafb51a7d0ff31a751b986172f68ea7
BLAKE2b-256 c272b1e2a51c0598774293a2de815c351c4bfc350d95a74d821d68ea6411720d

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