APAAI Protocol Python SDK — Action → Policy → Evidence
Project description
apaai-client
Python SDK for APAAI Protocol
Open, vendor-neutral SDK for the APAAI Protocol's Action → Policy → Evidence loop.
- 📦 Package:
apaai - 🔌 Protocol: HTTP/JSON (
/actions,/evidence,/policy) - 🧪 Minimal & testable: Class-based API
- 🧱 License: Apache-2.0
Install
pip install apaai
Reference server (for local development):
cd server npm i && npm run dev # → http://localhost:8787
Authentication
The SDK authenticates using an API key passed via the x-api-key HTTP header.
from apaai import AccountabilityLayer, AccountabilityLayerOptions
apaai = AccountabilityLayer(AccountabilityLayerOptions(
endpoint="https://api.apaai.ai", # or your self-hosted endpoint
api_key="sk_live_...", # your API key
))
Get your API key from the APAAI Dashboard.
You can also pass custom headers if needed:
apaai = AccountabilityLayer(AccountabilityLayerOptions(
endpoint="https://api.apaai.ai",
api_key="sk_live_...",
headers={"X-Custom-Header": "value"},
))
Quickstart
from apaai import AccountabilityLayer, AccountabilityLayerOptions
import os
# Initialize the accountability layer
apaai = AccountabilityLayer(AccountabilityLayerOptions(
endpoint="http://localhost:8787",
api_key=os.getenv("APAAI_API_KEY")
))
# 1) Propose an action
decision = apaai.propose(
type="send_email",
actor={"kind": "agent", "name": "mail-bot"},
target="mailto:client@acme.com",
params={"subject": "Proposal"}
)
# 2) Add evidence
apaai.evidence(decision["actionId"], [
{"name": "email_sent", "pass": True, "note": "msgId=123"}
])
API Reference
AccountabilityLayer Class
apaai = AccountabilityLayer(
endpoint: Optional[str] = None,
api_key: Optional[str] = None
)
Core Methods
propose(action)- Propose an action and get a decisionevidence(action_id, checks)- Submit evidence for an actionpolicy(action_type?)- Get policy for an action typeapprove(action_id, approver?)- Approve an actionreject(action_id, reason?)- Reject an actionget_action(action_id)- Get action detailslist_actions(filters?)- List actions with filtersget_evidence(action_id)- Get evidence for an actionset_policy(policy)- Set a policy
Manager Interfaces
apaai.policies.evaluate(action_id)- Evaluate policy for an actionapaai.policies.enforce(action_type)- Enforce policy for an action typeapaai.policies.set(policy)- Set a policyapaai.human.approve(action_id, approver?)- Approve an actionapaai.human.reject(action_id, reason?)- Reject an actionapaai.evidence.add(action_id, checks)- Add evidence for an actionapaai.evidence.get(action_id)- Get evidence for an actionapaai.actions.get(action_id)- Get action detailsapaai.actions.list(filters?)- List actions with filters
Examples
Basic Flow
from apaai import AccountabilityLayer
apaai = AccountabilityLayer(endpoint="http://localhost:8787")
# Propose action
decision = apaai.propose(
type="send_email",
actor={"kind": "agent", "name": "mail-bot"},
target="mailto:client@acme.com",
params={"subject": "Proposal"}
)
# Handle approval if required
if decision["status"] == "requires_approval":
apaai.approve(decision["actionId"], "@reviewer")
# Submit evidence
apaai.evidence.add(decision["actionId"], [
{"name": "email_sent", "pass": True, "note": "msgId=123"}
])
Human-in-the-Loop with Webhooks
Configure webhooks at the organization level in your APAAI dashboard to receive callbacks when actions are approved or rejected:
from apaai import propose
# Propose an action that requires approval
decision = propose(
type="send_payment",
actor={"kind": "agent", "name": "payment-bot"},
params={"amount": 5000, "recipient": "vendor@company.com"}
)
if decision["status"] == "requires_approval":
print("Awaiting approval:", decision["actionId"])
# Your org webhook will be notified when approved/rejected
# Your org webhook endpoint will receive:
# POST /webhooks/apaai
# {
# "event": "action.approved", # or "action.rejected"
# "timestamp": "2024-01-01T00:00:00Z",
# "data": {
# "actionId": "...",
# "agentName": "payment-bot",
# "actionType": "send_payment",
# "status": "approved",
# "reviewNote": "Approved by manager",
# "metadata": {"amount": 5000, ...}
# }
# }
Using Manager Interfaces
# Policy management
policy = apaai.policies.enforce("send_email")
apaai.policies.set({"rules": [...]})
# Human-in-the-loop
apaai.human.approve(action_id, "@reviewer")
apaai.human.reject(action_id, "Invalid recipient")
# Evidence management
apaai.evidence.add(action_id, [
{"name": "email_sent", "pass": True, "note": "msgId=123"}
])
evidence = apaai.evidence.get(action_id)
# Action management
action = apaai.actions.get(action_id)
actions = apaai.actions.list({"type": "send_email"})
Types
from typing import Dict, List, Optional, Any
Actor = Dict[str, Any] # {"kind": "agent", "name": "mail-bot", "provider": "openai"}
Action = Dict[str, Any] # {
"id": str,
"timestamp": str,
"type": str,
"actor": Actor,
"target": Optional[str],
"params": Optional[Dict[str, Any]],
"status": Optional[str],
"checks": Optional[List[str]]
}
Check = Dict[str, Any] # {"name": str, "pass": bool, "note": Optional[str]}
Evidence = Dict[str, Any] # {"actionId": str, "checks": List[Check]}
Decision = Dict[str, Any] # {"status": str, "checks": Optional[List[str]]}
PolicyRule = Dict[str, Any] # {
"when": Optional[Dict[str, str]], # {"action": str} or {"actionType": str}
"require": Optional[List[str]],
"mode": Optional[str] # "enforce" | "observe"
}
Policy = Dict[str, Any] # {"rules": List[PolicyRule]}
Testing
# Run tests
python -m pytest tests/
# Run tests with coverage
python -m pytest tests/ --cov=apaai_client
# Run specific test file
python -m pytest tests/test_client.py
Build & Publish
# Build the package
python -m build
# Publish to PyPI
python -m twine upload dist/*
License
Apache-2.0
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
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 apaai-0.2.1.tar.gz.
File metadata
- Download URL: apaai-0.2.1.tar.gz
- Upload date:
- Size: 11.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8059e4af959aaa73d3ee67b3d2ea59ba6c205f33b6932038c093147ddfa640ce
|
|
| MD5 |
914aa87db7f0f23a381e2f01951dcae2
|
|
| BLAKE2b-256 |
defbef208d3dddaaa36397f9950d824c3d9979c691165711c6daad1436cd7bee
|
File details
Details for the file apaai-0.2.1-py3-none-any.whl.
File metadata
- Download URL: apaai-0.2.1-py3-none-any.whl
- Upload date:
- Size: 10.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f935390efa70294879bdeb754794bc42072200de45d859a2fd1efb956a72c502
|
|
| MD5 |
b3059aae9c0c39938ee484e7562c1e90
|
|
| BLAKE2b-256 |
583a3fbcc720d1f952ed473805ff51c8d290aac7134f0f0d2855118f33861762
|