Python
Python SDK
Use the Python SDK when you want typed resource objects, synchronous or asynchronous calls, parsed provenance, and consistent error handling. The examples use the public v1 resource surface.
python -m pip install mpalo-sdk
Create a client
The constructor reads PALO_API_KEY when no key is supplied. It also resolves the configured base URL and validates key format. Pass an explicit key only when the value comes from a secure runtime source.
import os
from palo import Palo
client = Palo(
api_key=os.environ["PALO_API_KEY"],
timeout=30,
max_retries=2,
)from palo import AsyncPalo
async with AsyncPalo() as client:
result = await client.memory.recall("What is relevant?", top_k=3)Write, recall, and delete
The SDK validates non-empty text, namespace length, top-k bounds, and response contract fields before returning typed objects. Use a stable idempotency key for a logical event. Use namespaces to separate unrelated application contexts.
write = client.memory.write(
"The user moved the appointment to Monday afternoon.",
namespace="conversation",
event_id="message_7",
occurred_at="2026-08-28T10:00:00Z",
idempotency_key="conversation-42-message-7",
source={"type": "external_application", "id": "conversation-42-message-7"},
)
print(write.state)
print(write.decision)
print(write.source.type if write.source else None)
print(write.provenance.execution_mode)
print(write.usage.billing_state)
recall = client.memory.recall(
"When is the current appointment?",
namespace="conversation",
top_k=3,
as_of="2026-08-28T12:00:00Z",
)
print(recall.state, recall.proximity)
receipt = client.memory.delete(namespace="conversation")
print(receipt.state, receipt.deleted)Import and migration
The current v1 API does not expose a separate bulk-import job. The Python package can parse, chunk, deduplicate, checkpoint, and estimate an archive locally. A committed migration sends each chunk through client.memory.write as an ordinary imported_archive event, so the active storage connection, consent policy, usage meter, billing ledger, provenance, and observability rules still apply.
for record in records:
source_id = record["id"]
write = client.memory.write(
record["text"],
namespace="imported",
event_id=f"archive:{source_id}",
idempotency_key=f"archive:{source_id}",
occurred_at=record.get("occurred_at"),
source={"type": "imported_archive", "id": source_id},
metadata={"archive": "chatgpt-export-2026"},
)
print(write.state, write.decision, write.provenance)The source object is caller-attested metadata. It does not verify who originally created the record. The API key determines the remote account and tenant scope. The local dry-run estimate is not an invoice, does not call an external model, and does not replace the usage and billing response from committed writes.
Infrastructure resources
Infrastructure methods return the deployment and measurement context that produced the response. Use them for startup checks, dashboards, incident investigation, and release verification. A health response is self-describing and includes provider, model version, deployment version, and environment identity. The SDK rejects a response that omits or malforms those fields.
capabilities = client.infrastructure.capabilities() health = client.infrastructure.health() status = client.infrastructure.status() usage = client.infrastructure.usage(lookback_minutes=15) events = client.infrastructure.events(limit=100, offset=0) print(capabilities.operations) print(health.deployment_version, health.environment) print(status["monitoring"]["anomalies"]) print(usage["recorded_charge_usd"]) print(len(events["data"]))
The SDK also exposes metrics, anomalies, monitoring, and export. The async resource mirrors these methods.
Errors and safe retries
from palo import APIConnectionError, APITimeoutError, RateLimitError
try:
result = client.memory.write(text, idempotency_key="event-42")
except (APITimeoutError, APIConnectionError):
result = client.memory.write(text, idempotency_key="event-42")
except RateLimitError as error:
print(error, error.retry_after)A timeout means the server outcome may be unknown. Reuse the same idempotency key for a write and inspect the returned idempotency outcome.
Was this page helpful?
Your feedback helps us improve our documentation.