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_..."
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2d34c989b61463990d0c11cb3716686171cd6c0ae8523324eeb5cf60fda8215a
|
|
| MD5 |
bab9873b0c7406e8a6c463ea8c82c959
|
|
| BLAKE2b-256 |
855778db65e9781a7a1a570494c142120839afd3f8206060cd7954620616c1e4
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a0380ce135da92ff66a630f08cb29233eb97d8fa0f4a421fd49d527714d47bb5
|
|
| MD5 |
afafb51a7d0ff31a751b986172f68ea7
|
|
| BLAKE2b-256 |
c272b1e2a51c0598774293a2de815c351c4bfc350d95a74d821d68ea6411720d
|