decision_read
Reads data through a governed data product within a decision envelope. All data access is logged and auditable.
Overview
The decision_read method allows you to read data from a data product within a decision context. Data products provide governed access to underlying data sources (databases, APIs, etc.) with schema restrictions, purpose-based access control, and automatic audit logging.
Request
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
decision_id | string | Yes | The decision ID (from decision_create) |
product | string | Yes | Data product name (e.g., "pg_customers_v1") |
purpose | string | Yes | Why you're accessing the data (must be in the data product's allowed purposes) |
query | object | No | Query parameters for filtering data (varies by data product) |
allow_multiple | boolean | No | If false (default), limit results to 1. If true, allow multiple results |
Example Request
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "decision_read",
"arguments": {
"decision_id": "TMEM_abc123...",
"product": "pg_customers_v1",
"purpose": "order_validation",
"query": {
"customer_id": "1001"
},
"allow_multiple": false
}
}
}
Response
Success Response
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "{\"event_id\": \"evt_...\", \"product\": \"pg_customers_v1\", \"data_ref\": \"ref:read:...\", \"records\": [{\"customer_id\": 1001, \"name\": \"Acme Corp\", \"email\": \"contact@acme.com\"}], \"summary\": {\"rows\": 1, \"fields\": [\"customer_id\", \"name\", \"email\"]}}"
}
]
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
event_id | string | Unique identifier for this read event |
product | string | The data product that was accessed |
data_ref | string | Reference to the data (may be a reference rather than full data for privacy) |
records | array | Array of records returned (structure depends on data product schema) |
summary | object | Summary of the read operation |
summary.rows | number | Number of rows returned |
summary.fields | array | List of field names that were returned |
Example Response Data
{
"event_id": "evt_read_abc123",
"product": "pg_customers_v1",
"data_ref": "ref:read:xyz789",
"records": [
{
"customer_id": 1001,
"name": "Acme Corp",
"email": "contact@acme.com",
"tier": "premium",
"created_at": "2025-01-15T10:00:00Z"
}
],
"summary": {
"rows": 1,
"fields": ["customer_id", "name", "email", "tier", "created_at"]
}
}
Error Cases
Missing Required Parameters
Error Code: -32600 (Invalid Request)
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32600,
"message": "Invalid Request",
"data": "decision_id, product, and purpose are required"
}
}
Invalid Purpose
Error Code: -32603 (Internal error)
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32603,
"message": "Internal error",
"data": "Purpose 'invalid_purpose' is not allowed for this data product"
}
}
Common causes:
- Purpose not in the data product's
allowed_purposeslist - Purpose misspelled or incorrect
Data Product Not Found
Error Code: -32603 (Internal error)
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32603,
"message": "Internal error",
"data": "Data product 'pg_customers_v1' not found or not accessible"
}
}
Common causes:
- Data product doesn't exist
- Agent doesn't have read permission for this data product
- Data product name is misspelled
Permission Denied
HTTP Status: 403 Forbidden
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32603,
"message": "Internal error",
"data": "Permission denied: agent does not have read access to this data product"
}
}
Multiple Results Without allow_multiple
Error Code: -32603 (Internal error)
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32603,
"message": "Internal error",
"data": "Query returned multiple results but allow_multiple is false"
}
}
Solution: Set allow_multiple: true if you expect multiple results, or refine your query to return a single result.
Decision Not Found
Error Code: -32603 (Internal error)
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32603,
"message": "Internal error",
"data": "Decision not found"
}
}
Authentication Errors
HTTP Status: 401 Unauthorized
Occurs when:
- API key is missing
- API key is invalid
- API key has been revoked
Usage Examples
Read Single Customer Record
import requests
import json
def read_data(decision_id, product, purpose, query=None, allow_multiple=False, api_key=None):
response = requests.post('https://mcp.tracemem.com',
headers={'Authorization': f'Agent {api_key}'},
json={
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "decision_read",
"arguments": {
"decision_id": decision_id,
"product": product,
"purpose": purpose,
"query": query,
"allow_multiple": allow_multiple
}
}
})
result = response.json()
read_data = json.loads(result["result"]["content"][0]["text"])
return read_data
# Read customer data
customer = read_data(
decision_id="TMEM_abc123...",
product="pg_customers_v1",
purpose="order_validation",
query={"customer_id": "1001"},
api_key="YOUR_API_KEY"
)
if customer["records"]:
customer_data = customer["records"][0]
print(f"Customer: {customer_data['name']} ({customer_data['email']})")
Read Multiple Records
# Read all premium customers
customers = read_data(
decision_id=decision_id,
product="pg_customers_v1",
purpose="marketing_campaign",
query={"tier": "premium"},
allow_multiple=True,
api_key=api_key
)
print(f"Found {len(customers['records'])} premium customers")
for customer in customers["records"]:
print(f"- {customer['name']}: {customer['email']}")
Read with Complex Query
# Read orders for a specific customer within date range
orders = read_data(
decision_id=decision_id,
product="pg_orders_v1",
purpose="order_history",
query={
"customer_id": "1001",
"created_at__gte": "2025-01-01",
"created_at__lte": "2025-12-31",
"status": "completed"
},
allow_multiple=True,
api_key=api_key
)
Best Practices
-
Specify meaningful purposes: Use specific purposes that match your use case (e.g., "order_validation", "fraud_detection") rather than generic ones
-
Minimize data access: Use query filters to retrieve only the data you need. Don't read entire tables when you only need specific records
-
Filter by ID when possible: When looking up specific entities, filter by ID to minimize data exposure
-
Check allowed purposes: Use
product_getto check which purposes are allowed for a data product before reading -
Handle empty results: Always check if
recordsarray is empty before accessing data -
Use allow_multiple appropriately: Set
allow_multiple: trueonly when you expect or need multiple results -
Respect data minimization: Only request fields you need. Data products may automatically filter fields based on purpose
Important Notes
-
All reads are logged: Every read operation is recorded in the decision trace for audit purposes
-
Purpose-based access: The purpose you specify must be in the data product's
allowed_purposeslist -
Schema restrictions: Data products expose only specific fields and may transform data according to their configuration
-
Data references: Some sensitive data may be returned as references rather than full data for privacy
-
Query syntax: Query syntax varies by data product and underlying data source. Check data product documentation for supported query formats
-
Performance: Use specific queries (especially by ID) for better performance
Related Methods
decision_create- Create a decision (required before reading)product_get- Get data product details (check allowed purposes)products_list- List available data productsdecision_write- Write data through a data product