TraceMem Integration Guide for AI Agents
This document provides complete context for AI agents to integrate and build with TraceMem. Copy this entire document as context when working with TraceMem.
You can download this file as markdown using this link.
What is TraceMem?
TraceMem is a platform for capturing, organizing, and using "memory" from AI agents and applications across tools and sessions. It provides governed execution boundaries for agent decisions with automatic audit trails, policy enforcement, and human approval workflows.
Core Principle: Agents can request actions, but they never authorize them. TraceMem enforces governance, records evidence, and creates immutable audit trails.
Architecture Overview
TraceMem uses Agent MCP (Model Context Protocol), a JSON-RPC 2.0 server that provides standardized tools for all agent operations.
Connection:
- Endpoint:
https://mcp.tracemem.com - Protocol: JSON-RPC 2.0 over HTTP
- Authentication:
Authorization: Agent <api-key>header - Content-Type:
application/json
Initialization:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "my-agent", "version": "1.0.0"}
}
}
Core Concepts
1. Decision Envelopes
Every agent operation must start with a Decision Envelope - an execution boundary that tracks all operations within a decision context.
Required fields:
intent(string, required): Structured label describing why this decision exists (e.g.,"customer.order.create","renewal.discount.evaluate")automation_mode(string, required): One of:"propose"- Agent proposes, human decides"approve"- Agent executes after approval"override"- Human overrides policy"autonomous"- Agent executes without human approval
Lifecycle states:
open- Envelope created and activeneeds_approval- Decision requires human approvalapproved- Required approval has been grantedrejected- Required approval was rejectedcommitted- Decision completed successfully (terminal)aborted- Decision intentionally stopped (terminal)failed- Decision could not complete due to error (terminal)
Key principle: Always close decisions explicitly with decision_close (commit or rollback).
2. Data Products
Data Products are the ONLY way agents can read or write data in TraceMem. They are governed, purpose-bound interfaces to data.
Key properties:
- Each data product supports exactly one operation:
read,insert,update, ordelete - Every access must specify a
purposethat's in the data product'sallowed_purposes - Data products expose only a subset of the source schema
- All access is logged and auditable
- Data products are versioned and immutable once published
If you need multiple operations: Create separate data products (e.g., customer_data_read, customer_data_insert).
3. Policies
Policies are deterministic decision rules that determine whether actions are allowed.
Outcomes:
allow- Policy permits the actiondeny- Policy blocks the actionrequires_exception- Human approval required
Key points:
- Policies are evaluated at execution time
- Every evaluation is recorded in the decision trace
- Policies are versioned and immutable once published
- Policies never fetch data themselves - they operate on explicit inputs
4. Approvals
When a policy returns requires_exception, agents must request human approval.
Approval lifecycle:
- Agent requests approval via
decision_request_approval - Approval is delivered through configured integration (Slack, email, webhook)
- Agent polls for approval status using
decision_get - When approved, agent can proceed with writes
- When rejected or expired, agent must abort the decision
5. Decision Traces
Every decision creates an immutable Decision Trace - a permanent, queryable record of:
- What decision was made
- What data was accessed (with purposes)
- Which policies were checked
- Who approved exceptions
- What changed as a result
Trace structure:
- Decision Envelope - Identity and lifecycle
- Decision Events - Append-only timeline (reads, writes, policy evaluations, approvals)
- Decision Snapshots - Versions/hashes of policies, schemas, and data products at decision time
- Outcome Summary - Final result and metrics
Key principle: Traces are append-only and immutable. They preserve "why this was allowed" even if policies or data products change later.
6. Connectors
Connectors are connections to external data systems (databases, SaaS platforms). Agents never interact with Connectors directly - they access data through Data Products, which use Connectors under the hood.
Complete Agent Workflow
Standard Workflow Pattern
# 1. Initialize MCP client
client = MCPClient(api_key="your-api-key")
client.initialize()
decision_id = None
try:
# 2. Create decision envelope
decision = client.call_tool("decision_create", {
"intent": "customer.order.create",
"automation_mode": "propose",
"actor": "order-processing-agent"
})
decision_id = decision["decision_id"]
# 3. Read data through Data Product
customer = client.call_tool("decision_read", {
"decision_id": decision_id,
"product": "customer_data", # Data product ID
"purpose": "order_processing", # Must be in allowed_purposes
"query": {"customer_id": "123"}
})
# 4. Evaluate policy
policy_result = client.call_tool("decision_evaluate", {
"decision_id": decision_id,
"policy_id": "order_limit_v1",
"inputs": {"order_amount": 1000.00}
})
outcome = policy_result["outcome"]
# 5. Handle policy outcome
if outcome == "allow":
# Write data
write_result = client.call_tool("decision_write", {
"decision_id": decision_id,
"product": "orders", # Must have insert/update/delete operation enabled
"purpose": "order_creation",
"mutation": {
"operation": "insert", # or "update" or "delete"
"records": [{
"customer_id": "123",
"total": 1000.00
}]
}
})
elif outcome == "requires_exception":
# Request approval
approval = client.call_tool("decision_request_approval", {
"decision_id": decision_id,
"title": "Order Approval",
"message": "Customer requesting order above policy limit...",
"require_rationale": True,
"expires_in_seconds": 3600
})
# Poll for approval status
max_wait = 300 # 5 minutes
waited = 0
while waited < max_wait:
time.sleep(5)
decision_status = client.call_tool("decision_get", {
"decision_id": decision_id
})
status = decision_status["status"]
if status == "approved":
# Write data after approval
client.call_tool("decision_write", {...})
break
elif status == "rejected":
raise Exception("Approval rejected")
waited += 5
if waited >= max_wait:
raise Exception("Approval timeout")
elif outcome == "deny":
raise Exception("Action denied by policy")
# 6. Close decision (commit)
client.call_tool("decision_close", {
"decision_id": decision_id,
"action": "commit"
})
except Exception as e:
# Always close on error (rollback)
if decision_id:
client.call_tool("decision_close", {
"decision_id": decision_id,
"action": "rollback"
})
raise
Available MCP Tools
Decision Lifecycle
decision_create- Create a new decision envelopedecision_get- Get decision statusdecision_close- Close decision (commit or rollback)decision_trace- Get complete trace (self-access only)decision_receipt- Get cryptographic receipt
Data Access
decision_read- Read data through a Data Productdecision_write- Write data through a Data Product (insert/update/delete)
Policy Evaluation
decision_evaluate- Evaluate a policy
Approval Workflow
decision_request_approval- Request human approval
Context Events
decision_add_context- Add context event to trace
Discovery
products_list- List available Data Productsproduct_get- Get Data Product detailscapabilities_get- Get agent capabilities
API Reference
decision_create
Creates a new decision envelope.
Parameters:
intent(string, required): Why this decision existsautomation_mode(string, required):"propose","approve","override", or"autonomous"actor(string, optional): Human-readable actor identifierinstance(string, optional): Instance identifier for trackingversion(string, optional): SDK/agent versionmetadata(object, optional): Additional context metadata
Response:
{
"decision_id": "TMEM_abc123...",
"status": "open",
"created_at": "2026-01-07T12:00:00Z"
}
decision_read
Reads data through a Data Product.
Parameters:
decision_id(string, required): Decision ID fromdecision_createproduct(string, required): Data product namepurpose(string, required): Why accessing data (must be in allowed_purposes)query(object, optional): Query parameters for filteringallow_multiple(boolean, optional): Iffalse(default), limit to 1 result
Response:
{
"event_id": "evt_...",
"product": "customer_data",
"records": [...],
"summary": {"rows": 1, "fields": [...]}
}
decision_write
Writes data through a Data Product.
Parameters:
decision_id(string, required): Decision IDproduct(string, required): Data product namepurpose(string, required): Why writing datamutation(object, required): Mutation structureoperation(string, required):"insert","update", or"delete"records(array, required): Array of records to write
idempotency_key(string, optional): Key for idempotent writes
Response:
{
"event_id": "evt_...",
"status": "executed",
"mutation_summary": {"targets": 1},
"created_records": [...] // Only for insert when return_created is enabled
}
Important: Each data product supports exactly one operation. Use separate products for read, insert, update, and delete.
decision_evaluate
Evaluates a policy.
Parameters:
decision_id(string, required): Decision IDpolicy_id(string, required): Policy identifierinputs(object, required): Policy inputs
Response:
{
"outcome": "allow", // or "deny" or "requires_exception"
"rationale": "Policy rationale text",
"exception_route": {...} // Only if outcome is "requires_exception"
}
decision_request_approval
Requests human approval.
Parameters:
decision_id(string, required): Decision IDtitle(string, required): Approval request titlemessage(string, required): Approval request messagerequire_rationale(boolean, optional): Whether rationale is requiredexpires_in_seconds(number, optional): Expiration time
Response:
{
"approval_id": "apr_...",
"status": "requested"
}
Note: Poll for approval status using decision_get until status is "approved" or "rejected".
decision_close
Closes a decision (commit or rollback).
Parameters:
decision_id(string, required): Decision IDaction(string, required):"commit"or"rollback"
Response:
{
"status": "committed", // or "aborted"
"closed_at": "2026-01-07T12:05:00Z"
}
Critical: Always close decisions explicitly. Writes are only permanent when committed.
decision_get
Gets decision status.
Parameters:
decision_id(string, required): Decision ID
Response:
{
"decision_id": "TMEM_...",
"status": "open", // or "needs_approval", "approved", "committed", etc.
"created_at": "...",
"closed_at": null
}
Error Handling
JSON-RPC Error Format
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32600,
"message": "Invalid Request",
"data": "decision_id is required"
}
}
Common Error Codes
-32600Invalid Request - Missing required parameters-32601Method not found - Unknown tool name-32602Invalid params - Wrong parameter types-32603Internal error - Server error
HTTP Status Codes
200 OK- Success (even for JSON-RPC errors)401 Unauthorized- Invalid API key403 Forbidden- Permission denied429 Too Many Requests- Rate limited (includesRetry-Afterheader)
Error Handling Pattern
try:
result = client.call_tool("decision_read", {...})
except Exception as e:
if "401" in str(e) or "Unauthorized" in str(e):
# Invalid API key
raise Exception("Invalid API key")
elif "403" in str(e) or "Forbidden" in str(e):
# Permission denied
raise Exception("Permission denied")
elif "429" in str(e):
# Rate limited - retry later
raise Exception("Rate limited")
else:
# Other error
raise
Best Practices
1. Always Close Decisions
Use try-finally pattern to ensure decisions are always closed:
decision_id = None
try:
decision = client.call_tool("decision_create", {...})
decision_id = decision["decision_id"]
# ... perform operations ...
client.call_tool("decision_close", {"decision_id": decision_id, "action": "commit"})
except Exception as e:
if decision_id:
client.call_tool("decision_close", {"decision_id": decision_id, "action": "rollback"})
raise
2. Use Meaningful Intents
Follow hierarchical naming patterns:
customer.order.createrenewal.discount.evaluatesupport.ticket.escalate
3. Specify Explicit Purposes
Use specific purposes for data access:
order_processing(notgeneral)fraud_detection(notaccess)support_triage(notread)
4. Evaluate Policies Before Actions
Always evaluate policies before performing actions:
policy_result = client.call_tool("decision_evaluate", {...})
if policy_result["outcome"] == "allow":
# Proceed with action
elif policy_result["outcome"] == "requires_exception":
# Request approval
elif policy_result["outcome"] == "deny":
# Abort decision
5. Handle All Policy Outcomes
Don't assume policies will always return allow. Handle all three outcomes:
allow→ Proceedrequires_exception→ Request approvaldeny→ Abort
6. Minimize Data Access
- Filter by ID when possible
- Only read what you need
- Use specific queries, not full table scans
7. Use Idempotency Keys
For writes that may be retried:
client.call_tool("decision_write", {
"decision_id": decision_id,
"product": "orders",
"purpose": "order_creation",
"mutation": {...},
"idempotency_key": f"order-{customer_id}-{timestamp}"
})
8. Poll for Approvals Correctly
Handle timeouts and rejections:
max_wait = 300 # 5 minutes
waited = 0
while waited < max_wait:
time.sleep(5)
decision_status = client.call_tool("decision_get", {"decision_id": decision_id})
status = decision_status["status"]
if status == "approved":
break
elif status == "rejected":
raise Exception("Approval rejected")
waited += 5
if waited >= max_wait:
raise Exception("Approval timeout")
9. Check Data Product Configuration
Before reading/writing, check data product details:
product = client.call_tool("product_get", {"product": "customer_data"})
# Check allowed_purposes, exposed schema, allowed operations
10. Store Context Events
Record agent reasoning for auditability:
client.call_tool("decision_add_context", {
"decision_id": decision_id,
"summary": "Agent determined discount is appropriate based on customer history",
"payload": {"confidence": 0.95, "reasoning": "..."}
})
Data Product Operations
Critical: Each data product supports exactly one operation. If you need multiple operations, use separate data products.
Read Operation
Data product must have read operation enabled:
result = client.call_tool("decision_read", {
"decision_id": decision_id,
"product": "customer_data", # Must have read enabled
"purpose": "order_processing",
"query": {"customer_id": "123"}
})
Insert Operation
Data product must have insert operation enabled:
result = client.call_tool("decision_write", {
"decision_id": decision_id,
"product": "orders", # Must have insert enabled
"purpose": "order_creation",
"mutation": {
"operation": "insert",
"records": [{"customer_id": "123", "total": 1000.00}]
}
})
# If return_created is enabled, created records are returned
if "created_records" in result:
order_id = result["created_records"][0]["order_id"]
Update Operation
Data product must have update operation enabled:
result = client.call_tool("decision_write", {
"decision_id": decision_id,
"product": "orders", # Must have update enabled
"purpose": "order_fulfillment",
"mutation": {
"operation": "update",
"records": [{"order_id": 12345, "status": "shipped"}]
}
})
Delete Operation
Data product must have delete operation enabled:
result = client.call_tool("decision_write", {
"decision_id": decision_id,
"product": "orders", # Must have delete enabled
"purpose": "order_cancellation",
"mutation": {
"operation": "delete",
"records": [{"order_id": 12345}]
}
})
Security Model
Trust Boundaries
TraceMem treats agents as untrusted by default:
- Agent code is not trusted
- Agent logic may be buggy, malicious, or misconfigured
- Agents may attempt unsafe shortcuts
Key guarantee: Agents can request actions, never authorize them.
Authentication
Agents authenticate using Agent API keys:
- Tenant-scoped
- Grant access to specific Data Products
- Provide policy evaluation capabilities
- Enable approval request channels
Get API key:
- Navigate to Settings → Agents in dashboard
- Create an agent (if needed)
- Create a credential to get an API key
- Save securely (shown only once)
Authorization
TraceMem enforces authorization at multiple levels:
- API Key Scope - What Data Products the agent can access
- Data Product Permissions - What operations are allowed
- Purpose Restrictions - What purposes are allowed
- Policy Evaluations - Whether actions are allowed
- Approval Requirements - Whether human approval is needed
Agents cannot bypass any of these checks.
Rate Limits
- 100 requests/second per API key
- 1000 decisions/hour per agent
- 10 MB maximum request size
Exceeded limits return HTTP 429 with Retry-After header.
Setup Requirements
Before agents can use TraceMem, administrators must set up:
- Connector - Connection to data source (database, SaaS)
- Data Product - Governed interface to data (with allowed purposes and operations)
- Agent - API key for authentication
- Integration (optional) - Approval delivery channels (Slack, email, webhook)
- Approval Route (optional) - Approval routing configuration
- Policy (optional) - Business rules
Agents cannot create or modify these components - they are created by administrators via the dashboard or Admin API.
Mental Models
Decision Envelope
The Decision Envelope is the courtroom.
Evidence (data) is presented.
Rules (policies) are applied.
Judgment (approval or autonomy) is rendered.
The verdict (outcome) is recorded forever.
Data Products
Connectors are the plumbing.
Data Products are the faucets.
Agents turn on the faucets, but they never see the plumbing.
The plumbing knows how to get water from the source.
The faucets control how much water flows and for what purpose.
Decision Traces
The Decision Trace is the courtroom transcript.
Every piece of evidence (data read) is recorded.
Every rule checked (policy evaluation) is documented.
Every judgment (approval) is captured.
The verdict (outcome) is preserved forever.
Years later, you can still read the transcript and understand exactly what happened and why.
Quick Reference
MCP Client Implementation (Python)
import requests
import json
class MCPClient:
def __init__(self, api_key):
self.base_url = "https://mcp.tracemem.com"
self.api_key = api_key
self.session = requests.Session()
self.session.headers.update({
"Authorization": f"Agent {api_key}",
"Content-Type": "application/json"
})
self.request_id = 0
def _next_id(self):
self.request_id += 1
return self.request_id
def _call(self, method, params=None):
request = {
"jsonrpc": "2.0",
"id": self._next_id(),
"method": method,
"params": params or {}
}
response = self.session.post(self.base_url, json=request)
response.raise_for_status()
result = response.json()
if "error" in result:
error = result["error"]
raise Exception(f"MCP Error {error['code']}: {error['message']}")
return result.get("result", {})
def initialize(self):
return self._call("initialize", {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "my-agent", "version": "1.0.0"}
})
def call_tool(self, name, arguments):
result = self._call("tools/call", {
"name": name,
"arguments": arguments
})
if "content" in result and len(result["content"]) > 0:
text_content = result["content"][0].get("text", "{}")
try:
return json.loads(text_content)
except json.JSONDecodeError:
return {"raw_text": text_content}
return result
Complete Workflow Example
import os
import time
# Initialize
mcp_url = os.getenv("MCP_AGENT_URL", "https://mcp.tracemem.com")
api_key = os.getenv("TRACEMEM_API_KEY")
client = MCPClient(mcp_url, api_key)
client.initialize()
decision_id = None
try:
# Create decision
decision = client.call_tool("decision_create", {
"intent": "customer.order.create",
"automation_mode": "propose"
})
decision_id = decision["decision_id"]
# Read data
customer = client.call_tool("decision_read", {
"decision_id": decision_id,
"product": "customer_data",
"purpose": "order_processing",
"query": {"customer_id": "123"}
})
# Evaluate policy
policy_result = client.call_tool("decision_evaluate", {
"decision_id": decision_id,
"policy_id": "order_limit_v1",
"inputs": {"order_amount": 1000.00}
})
# Handle outcome
if policy_result["outcome"] == "allow":
client.call_tool("decision_write", {
"decision_id": decision_id,
"product": "orders",
"purpose": "order_creation",
"mutation": {
"operation": "insert",
"records": [{"customer_id": "123", "total": 1000.00}]
}
})
client.call_tool("decision_close", {
"decision_id": decision_id,
"action": "commit"
})
elif policy_result["outcome"] == "requires_exception":
client.call_tool("decision_request_approval", {
"decision_id": decision_id,
"title": "Order Approval",
"message": "Order above policy limit",
"expires_in_seconds": 3600
})
# Poll for approval...
client.call_tool("decision_close", {
"decision_id": decision_id,
"action": "commit"
})
else:
raise Exception("Action denied")
except Exception as e:
if decision_id:
client.call_tool("decision_close", {
"decision_id": decision_id,
"action": "rollback"
})
raise
Summary
TraceMem provides:
- Governed execution boundaries for agent decisions
- Automatic audit trails of all operations
- Policy enforcement with human approval workflows
- Purpose-bound data access through Data Products
- Immutable decision traces that preserve "why" forever
Key principles:
- Always create a Decision Envelope before any operation
- Access data only through Data Products with explicit purposes
- Evaluate policies before taking actions
- Request approvals when policies require exceptions
- Always close decisions explicitly (commit or rollback)
- Each data product supports exactly one operation
Remember: Agents can request actions, but they never authorize them. TraceMem enforces governance and creates immutable audit trails.