decision_write

Writes data through a governed data product within a decision envelope. All write operations are logged and only committed when the decision is closed with "commit".

Overview

The decision_write method allows you to insert, update, or delete data through a data product within a decision context. Write operations are validated according to the data product's configuration and are only made permanent when you close the decision with action: "commit".

Request

Parameters

ParameterTypeRequiredDescription
decision_idstringYesThe decision ID (from decision_create)
productstringYesData product name (e.g., "pg_orders_v1")
purposestringYesWhy you're writing the data (must be allowed by the data product)
mutationobjectYesThe mutation to perform (see Mutation Structure below)
idempotency_keystringNoKey for idempotent writes (prevents duplicate writes on retries)

Mutation Structure

The mutation object must contain:

FieldTypeRequiredDescription
operationstringYesMust be "insert", "update", or "delete"
recordsarrayYes*Array of records to write (required for all operations)
dataobjectYes*Single record to write (alternative to records for insert operations)

* For insert operations, you can use either data (single record) or records (array). For update and delete, use records.

Example Request - Insert

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "decision_write",
    "arguments": {
      "decision_id": "TMEM_abc123...",
      "product": "pg_orders_v1",
      "purpose": "order_creation",
      "mutation": {
        "operation": "insert",
        "records": [
          {
            "customer_id": 1001,
            "product_id": 5,
            "quantity": 1,
            "total_amount": 299.99
          }
        ]
      },
      "idempotency_key": "order-1001-20260107-001"
    }
  }
}

Example Request - Update

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "decision_write",
    "arguments": {
      "decision_id": "TMEM_abc123...",
      "product": "pg_orders_v1",
      "purpose": "order_update",
      "mutation": {
        "operation": "update",
        "records": [
          {
            "order_id": 12345,
            "status": "shipped",
            "shipped_at": "2026-01-07T14:00:00Z"
          }
        ]
      }
    }
  }
}

Example Request - Delete

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "decision_write",
    "arguments": {
      "decision_id": "TMEM_abc123...",
      "product": "pg_orders_v1",
      "purpose": "order_cancellation",
      "mutation": {
        "operation": "delete",
        "records": [
          {
            "order_id": 12345
          }
        ]
      }
    }
  }
}

Response

Success Response

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"event_id\": \"evt_...\", \"status\": \"executed\", \"mutation_summary\": {\"targets\": 1, \"fields_changed\": []}, \"created_records\": [...]}"
      }
    ]
  }
}

Response Fields

FieldTypeDescription
event_idstringUnique identifier for this write event
statusstringStatus of the write operation (typically "executed")
mutation_summaryobjectSummary of the mutation
mutation_summary.targetsnumberNumber of records affected
mutation_summary.fields_changedarrayList of fields that were changed (for updates)
created_recordsarrayArray of created records with generated IDs (only for insert operations when return_created is enabled)

Example Response - Insert with Returned Records

json
{
  "event_id": "evt_write_abc123",
  "status": "executed",
  "mutation_summary": {
    "targets": 1,
    "fields_changed": []
  },
  "created_records": [
    {
      "order_id": 12345,
      "customer_id": 1001,
      "product_id": 5,
      "quantity": 1,
      "total_amount": 299.99,
      "created_at": "2026-01-15T10:30:00Z"
    }
  ]
}

Note: The created_records field is only present when:

  • The operation is insert
  • The data product has restrictions.insert_config.return_created set to true
  • The insert operation succeeds

Insert Operation Validation

For insert operations, the following validation rules apply:

1. Required Columns

All columns marked as required: true in the data product's insert_config.column_config must be provided in the mutation data.

Error if missing:

json
{
  "error": {
    "code": -32603,
    "message": "Internal error",
    "data": "Validation failed: required column 'customer_id' is missing"
  }
}

2. Allowed Columns

Only columns marked as allowed: true (or not explicitly disallowed) in insert_config.column_config can be included. Columns not in the exposed schema are also rejected.

Error if disallowed:

json
{
  "error": {
    "code": -32603,
    "message": "Internal error",
    "data": "Validation failed: column 'internal_notes' is not allowed"
  }
}

3. Primary Key Handling

For primary keys with auto-generated defaults (sequences, auto_increment, UUIDs):

  • If allow_custom_primary_key[item_id] is false or not set, custom values will be rejected
  • If allow_custom_primary_key[item_id] is true, custom values are allowed

Error if custom primary key not allowed:

json
{
  "error": {
    "code": -32603,
    "message": "Internal error",
    "data": "Validation failed: custom primary key value not allowed for 'order_id'"
  }
}

4. Default Values

Columns can have default behaviors configured:

  • "user_provided" - User must provide the value
  • "db_default" - Database default is used (column can be omitted)
  • "tracemem_default" - Fixed default value is used (specified in tracemem_default_value)
  • "null" - Column is set to NULL (only for nullable columns)

Error Cases

Missing Required Parameters

Error Code: -32600 (Invalid Request)

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32600,
    "message": "Invalid Request",
    "data": "decision_id, product, purpose, and mutation are required"
  }
}

Invalid Operation

Error Code: -32602 (Invalid params)

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32602,
    "message": "Invalid params",
    "data": "mutation.operation must be one of: insert, update, delete"
  }
}

Validation Errors

Error Code: -32603 (Internal error)

Common validation errors:

  • Missing required columns
  • Disallowed columns in the request
  • Primary key custom values not allowed
  • Invalid default value configurations
  • Invalid data types
json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32603,
    "message": "Internal error",
    "data": "Validation failed: required column 'customer_id' is missing. Tip: Check that all required columns are provided and only allowed columns are included."
  }
}

Policy Evaluation Required

Error Code: -32603 (Internal error)

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32603,
    "message": "Internal error",
    "data": "Policy evaluation required before write operation. Tip: Use the 'decision_evaluate' tool to evaluate the required policy(ies) before performing write operations."
  }
}

Solution: Evaluate the required policy using decision_evaluate before performing the write.

Data Product Not Found

Error Code: -32603 (Internal error)

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32603,
    "message": "Internal error",
    "data": "Data product 'pg_orders_v1' not found or not accessible"
  }
}

Permission Denied

HTTP Status: 403 Forbidden

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32603,
    "message": "Internal error",
    "data": "Permission denied: agent does not have write access to this data product"
  }
}

Decision Not Found or Closed

Error Code: -32603 (Internal error)

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32603,
    "message": "Internal error",
    "data": "Decision not found or already closed"
  }
}

Authentication Errors

HTTP Status: 401 Unauthorized

Occurs when:

  • API key is missing
  • API key is invalid
  • API key has been revoked

Usage Examples

Insert Single Record

python
import requests
import json

def write_data(decision_id, product, purpose, mutation, idempotency_key=None, 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_write",
                "arguments": {
                    "decision_id": decision_id,
                    "product": product,
                    "purpose": purpose,
                    "mutation": mutation,
                    "idempotency_key": idempotency_key
                }
            }
        })
    
    result = response.json()
    if "error" in result:
        raise Exception(result["error"]["data"])
    
    write_data = json.loads(result["result"]["content"][0]["text"])
    return write_data

# Insert order
result = write_data(
    decision_id="TMEM_abc123...",
    product="pg_orders_v1",
    purpose="order_creation",
    mutation={
        "operation": "insert",
        "records": [{
            "customer_id": 1001,
            "product_id": 5,
            "quantity": 1,
            "total_amount": 299.99
        }]
    },
    idempotency_key=f"order-1001-{int(time.time())}",
    api_key="YOUR_API_KEY"
)

# Check if created records were returned
if "created_records" in result:
    order_id = result["created_records"][0]["order_id"]
    print(f"Order created with ID: {order_id}")

Insert Multiple Records

python
# Insert multiple order items
result = write_data(
    decision_id=decision_id,
    product="pg_order_items_v1",
    purpose="order_creation",
    mutation={
        "operation": "insert",
        "records": [
            {"order_id": 12345, "product_id": 5, "quantity": 2, "price": 99.99},
            {"order_id": 12345, "product_id": 8, "quantity": 1, "price": 149.99}
        ]
    },
    api_key=api_key
)

Update Record

python
# Update order status
result = write_data(
    decision_id=decision_id,
    product="pg_orders_v1",
    purpose="order_fulfillment",
    mutation={
        "operation": "update",
        "records": [{
            "order_id": 12345,
            "status": "shipped",
            "shipped_at": "2026-01-07T14:00:00Z",
            "tracking_number": "TRACK123"
        }]
    },
    api_key=api_key
)

Delete Record

python
# Cancel order
result = write_data(
    decision_id=decision_id,
    product="pg_orders_v1",
    purpose="order_cancellation",
    mutation={
        "operation": "delete",
        "records": [{
            "order_id": 12345
        }]
    },
    api_key=api_key
)

Best Practices

  1. Evaluate policies first: Use decision_evaluate to check policies before writing data

  2. Use idempotency keys: Include idempotency_key for writes that may be retried to prevent duplicates

  3. Check data product configuration: Use product_get to understand required/allowed columns and validation rules

  4. Validate before writing: Ensure all required fields are present and data types are correct

  5. Handle validation errors: Provide clear error messages to users when validation fails

  6. Commit decisions: Remember that writes are only permanent when you close the decision with action: "commit"

  7. Use appropriate purposes: Specify purposes that match your use case and are allowed by the data product

  8. Batch operations: When inserting multiple records, use the records array rather than multiple separate calls

Important Notes

  • Writes are not immediate: Writes are staged and only committed when you close the decision with action: "commit"

  • Approval may be required: If a decision requires approval, writes are blocked until approval is granted

  • Rollback on abort: If you close a decision with action: "abort", all writes within that decision are rolled back

  • Validation is strict: All validation rules must be satisfied or the write will fail

  • Policy evaluation: Some data products require policy evaluation before writes are allowed

  • Created records: The created_records field is only returned for insert operations when the data product is configured to return them

Related Methods

  • decision_create - Create a decision (required before writing)
  • decision_evaluate - Evaluate policies before writing
  • decision_close - Commit or abort the decision (makes writes permanent or rolls them back)
  • product_get - Get data product details (check write permissions and validation rules)

TraceMem is trace-native infrastructure for AI agents