Quickstart
Get your first decision trace stored in TraceMem in 5 minutes. This guide covers the minimum workflow to create an immutable audit trail of an agent decision.
What You'll Build
A simple agent that reads data through TraceMem and creates a decision trace—the foundation for explainable, auditable AI decisions.
Prerequisites
- TraceMem account (sign up)
- Access to a PostgreSQL-based database (e.g., PlanetScale or Supabase)
Example Database Schema
For this guide, we'll use a simple customers table. Create it in your PostgreSQL database:
sql
CREATE TABLE customers (
customer_id SERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
tier VARCHAR(50) DEFAULT 'standard',
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Insert sample data
INSERT INTO customers (email, name, tier) VALUES
('alice@example.com', 'Alice Smith', 'premium'),
('bob@example.com', 'Bob Jones', 'standard'),
('charlie@example.com', 'Charlie Brown', 'enterprise');
Step 1: Connect Your Data (2 minutes)
Create a Connector
- Go to Setup → Connectors in the dashboard
- Click Create Connector
- Select Database and your system type
- Enter a connection string:
PostgreSQL:
text
postgresql://username:password@host:5432/database?sslmode=require
- Click Create and verify connection status is
connected
Create a Data Product
- Go to Config → Data Products
- Click Create Data Product
- Select Source:
- Select Read operation
- Choose your connector
- Select the
customerstable (or your table)
- Choose columns:
- Select the
customer_idas required
- Select the
- Fill in:
- Product Name:
customer_data(or your choice) - Description: "Customer information for agent access"
- Set Allowed Purposes: add purpose:
order_processing
- Product Name:
- Review and Create data product
- Publish the data product
Step 2: Get Your API Key (1 minute)
- Go to Settings → Agents
- Click Create Agent
- Enter agent name:
my-first-agent - Click Create Credential
- Copy and save the API key (shown only once)
Step 3: Make Your First Decision (2 minutes)
Choose your language and run the example:
Python
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 _call(self, method, params=None):
request = {
"jsonrpc": "2.0",
"id": self.request_id := self.request_id + 1,
"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:
raise Exception(f"Error: {result['error']}")
return result.get("result", {})
def call_tool(self, name, arguments):
result = self._call("tools/call", {
"name": name,
"arguments": arguments
})
if "content" in result and len(result["content"]) > 0:
return json.loads(result["content"][0].get("text", "{}"))
return result
# Initialize
client = MCPClient("your-api-key-here")
client._call("initialize", {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "my-first-agent", "version": "1.0.0"}
})
# 1. Create decision envelope
decision = client.call_tool("decision_create", {
"intent": "customer.lookup",
"automation_mode": "autonomous"
})
decision_id = decision["decision_id"]
print(f"Created decision: {decision_id}")
# 2. Read data through Data Product
customer = client.call_tool("decision_read", {
"decision_id": decision_id,
"product": "customer_data", # Your data product ID
"purpose": "order_processing",
"query": {"customer_id": 1} # Query by customer_id
})
print(f"Read customer: {customer.get('records', [])}")
# 3. Close decision (commits the trace)
result = client.call_tool("decision_close", {
"decision_id": decision_id,
"action": "commit"
})
print(f"Decision closed: {result.get('status')}")
TypeScript
typescript
import fetch from 'node-fetch'; // or use native fetch in Node 18+
class MCPClient {
private baseUrl: string;
private apiKey: string;
private requestId: number = 0;
constructor(apiKey: string) {
this.baseUrl = "https://mcp.tracemem.com";
this.apiKey = apiKey;
}
private async call(method: string, params?: any): Promise<any> {
const request = {
jsonrpc: "2.0",
id: ++this.requestId,
method,
params: params || {}
};
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: {
'Authorization': `Agent ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(request)
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const result = await response.json();
if (result.error) {
throw new Error(`Error: ${JSON.stringify(result.error)}`);
}
return result.result || {};
}
async callTool(name: string, arguments_: any): Promise<any> {
const result = await this.call("tools/call", {
name,
arguments: arguments_
});
if (result.content && result.content.length > 0) {
return JSON.parse(result.content[0].text || "{}");
}
return result;
}
}
// Initialize and run
async function main() {
const client = new MCPClient("your-api-key-here");
await client.call("initialize", {
protocolVersion: "2024-11-05",
capabilities: {},
clientInfo: { name: "my-first-agent", version: "1.0.0" }
});
// 1. Create decision envelope
const decision = await client.callTool("decision_create", {
intent: "customer.lookup",
automation_mode: "autonomous"
});
const decisionId = decision.decision_id;
console.log(`Created decision: ${decisionId}`);
// 2. Read data through Data Product
const customer = await client.callTool("decision_read", {
decision_id: decisionId,
product: "customer_data", // Your data product ID
purpose: "order_processing",
query: { customer_id: 1 } // Query by customer_id
});
console.log(`Read customer:`, customer.records || []);
// 3. Close decision (commits the trace)
const result = await client.callTool("decision_close", {
decision_id: decisionId,
action: "commit"
});
console.log(`Decision closed: ${result.status}`);
}
main().catch(console.error);
Install dependencies:
- Python:
pip install requests - TypeScript:
npm install node-fetch @types/node-fetch(or use native fetch in Node 18+)
Run either script. You've created your first decision trace!
Step 4: View Your Trace
- Go to Traces in the dashboard
- Find your decision by
decision_idor intentcustomer.lookup - Click to view the complete trace:
- Decision envelope (intent, status, timestamps)
- Events (read operation with purpose)
- Decision-time snapshot (data product version)
- Outcome summary
What Just Happened?
You created an immutable decision trace that records:
- What decision was made:
customer.lookup - What data was accessed: Customer data via
customer_dataproduct - Why it was accessed: Purpose
order_processing - When it happened: Exact timestamps
- What version applied: Data product hash in snapshot
This trace will remain queryable and auditable forever, even if your data product changes.