Python Agent Examples

This guide provides complete, runnable examples for building TraceMem agents in Python. Each example demonstrates a specific pattern for interacting with TraceMem's Agent MCP server.

Prerequisites

  • Python 3.8 or higher
  • requests library: pip install requests
  • Access to a TraceMem Agent MCP server (default: https://mcp.tracemem.com)
  • A valid TraceMem API key

Connection Details

  • Endpoint: https://mcp.tracemem.com (or set via MCP_AGENT_URL environment variable)
  • Protocol: JSON-RPC 2.0 over HTTP
  • Authentication: Authorization: Agent <your-api-key> header

MCP Client Implementation

First, let's create a reusable MCP client class that handles JSON-RPC 2.0 communication:

python
import requests
import json
import os
from typing import Dict, Any, Optional


class MCPClient:
    """MCP Client for interacting with TraceMem Agent MCP Server"""
    
    def __init__(self, base_url: str, api_key: str):
        self.base_url = base_url
        self.api_key = api_key
        self.request_id = 0
        self.initialized = False
        self.session = requests.Session()
        self.session.headers.update({
            'Authorization': f'Agent {api_key}',
            'Content-Type': 'application/json',
        })
    
    def _next_id(self) -> int:
        """Get next request ID"""
        self.request_id += 1
        return self.request_id
    
    def _call(self, method: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """Make a JSON-RPC call to MCP server"""
        request = {
            'jsonrpc': '2.0',
            'id': self._next_id(),
            'method': method,
            'params': params or {},
        }
        
        try:
            response = self.session.post(self.base_url, json=request)
            response.raise_for_status()
            result = response.json()
            
            if 'error' in result:
                error = result['error']
                error_msg = f"MCP Error {error.get('code', 'unknown')}: {error.get('message', 'Unknown error')}"
                if 'data' in error:
                    error_msg += f" - {json.dumps(error['data'])}"
                raise Exception(error_msg)
            
            return result.get('result', {})
        except requests.exceptions.RequestException as e:
            raise Exception(f"HTTP Error: {str(e)}")
    
    def initialize(self) -> Dict[str, Any]:
        """Initialize MCP session"""
        result = self._call('initialize', {
            'protocolVersion': '2024-11-05',
            'capabilities': {},
            'clientInfo': {
                'name': 'tracemem-test-agent',
                'version': '1.0.0',
            },
        })
        self.initialized = True
        return result
    
    def list_tools(self) -> Dict[str, Any]:
        """List available tools"""
        return self._call('tools/list')
    
    def call_tool(self, name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
        """Call a tool"""
        if not self.initialized:
            self.initialize()
        
        result = self._call('tools/call', {
            'name': name,
            'arguments': arguments,
        })
        
        # Check if the tool result indicates an error
        if result.get('isError'):
            error_message = 'Tool call failed'
            if result.get('content') and len(result['content']) > 0:
                content = result['content'][0]
                if content.get('type') == 'text' and content.get('text'):
                    error_message = content['text']
            raise Exception(error_message)
        
        # Parse content from tool result
        if result.get('content') and len(result['content']) > 0:
            content = result['content'][0]
            if content.get('type') == 'text' and content.get('text'):
                try:
                    return json.loads(content['text'])
                except json.JSONDecodeError:
                    return {'raw_text': content['text']}
        
        return result
    
    def is_initialized(self) -> bool:
        """Check if client is initialized"""
        return self.initialized

Example 1: Read Agent

This example demonstrates reading customer data from a data product.

python
#!/usr/bin/env python3
"""
Read Test Agent

Tests the read operation on planetscale_read_customer_v1 data product.
This agent:
1. Creates a decision envelope
2. Reads customer data using decision_read
3. Closes the decision envelope
"""

import os
import sys
from mcp_client import MCPClient


def run_read_test():
    # Get configuration from environment
    mcp_url = os.getenv('MCP_AGENT_URL', 'https://mcp.tracemem.com')
    api_key = os.getenv('TRACEMEM_API_KEY')
    instance = os.getenv('TRACEMEM_INSTANCE')
    actor = os.getenv('TRACEMEM_ACTOR', 'test-read-agent')
    customer_id = os.getenv('CUSTOMER_ID', '1003')
    
    if not api_key:
        print('ERROR: TRACEMEM_API_KEY environment variable is required', file=sys.stderr)
        sys.exit(1)
    
    print('=' * 60)
    print('TraceMem MCP - Read Test Agent')
    print('=' * 60)
    print()
    print(f'Connecting to Agent MCP at: {mcp_url}')
    if instance:
        print(f'Instance: {instance}')
    print(f'Actor: {actor}')
    print(f'Customer ID: {customer_id}')
    print()
    
    client = MCPClient(mcp_url, api_key)
    decision_id = None
    
    try:
        # Initialize MCP session
        print('Initializing MCP session...')
        init_result = client.initialize()
        server_name = init_result.get('serverInfo', {}).get('name', 'TraceMem Agent MCP')
        print(f'✓ Connected to {server_name}')
        print()
        
        # Step 1: Create decision envelope
        print('Step 1: Creating decision envelope...')
        decision = client.call_tool('decision_create', {
            'intent': 'test.read.customer',
            'automation_mode': 'autonomous',
            'instance': instance,
            'actor': actor,
            'metadata': {
                'customer_id': customer_id,
                'test_type': 'read',
            },
        })
        
        decision_id = decision.get('decision_id') or decision.get('id')
        if not decision_id:
            raise Exception('Failed to get decision_id from decision_create response')
        print(f'✓ Decision envelope created: {decision_id}')
        print()
        
        # Step 2: Read customer data
        print('Step 2: Reading customer data...')
        read_result = client.call_tool('decision_read', {
            'decision_id': decision_id,
            'product': 'planetscale_read_customer_v1',
            'purpose': 'web_order',
            'query': {
                'id': int(customer_id),
            },
        })
        
        print('✓ Customer data retrieved')
        if read_result.get('event_id'):
            print(f'  Event ID: {read_result["event_id"]}')
        if read_result.get('data_ref'):
            print(f'  Data Reference: {read_result["data_ref"]}')
        if read_result.get('records') and len(read_result['records']) > 0:
            print(f'  Records found: {len(read_result["records"])}')
            print('  Customer data:')
            print(json.dumps(read_result['records'][0], indent=2))
        else:
            print('  No records found')
        print()
        
        # Step 3: Close decision (commit)
        print('Step 3: Committing decision...')
        close_result = client.call_tool('decision_close', {
            'decision_id': decision_id,
            'action': 'commit',
        })
        print('✓ Decision committed')
        if close_result.get('status'):
            print(f'  Status: {close_result["status"]}')
        print()
        
        # Summary
        print('=' * 60)
        print('Summary')
        print('=' * 60)
        print(f'Decision ID: {decision_id}')
        print('Result: ✓ Read operation completed successfully')
        print()
        
    except Exception as error:
        print(f'✗ Error: {str(error)}', file=sys.stderr)
        import traceback
        traceback.print_exc()
        
        # Try to close decision on error
        if decision_id:
            try:
                print('Attempting to abort decision...')
                client.call_tool('decision_close', {
                    'decision_id': decision_id,
                    'action': 'abort',
                    'reason': f'Error occurred: {str(error)}',
                })
                print('✓ Decision aborted')
            except Exception as close_error:
                print(f'Failed to abort decision: {str(close_error)}', file=sys.stderr)
        
        sys.exit(1)


if __name__ == '__main__':
    run_read_test()

Environment Variables

  • TRACEMEM_API_KEY (required): Your TraceMem agent API key
  • MCP_AGENT_URL (optional): MCP server URL (default: https://mcp.tracemem.com)
  • TRACEMEM_INSTANCE (optional): Instance identifier
  • TRACEMEM_ACTOR (optional): Actor identifier (default: test-read-agent)
  • CUSTOMER_ID (optional): Customer ID to read (default: 1003)

Running the Example

bash
export TRACEMEM_API_KEY="your-api-key"
export CUSTOMER_ID="1"
python test_read_agent.py

Example 2: Insert Agent (with Policy)

This example demonstrates inserting an order with policy evaluation.

python
#!/usr/bin/env python3
"""
Insert Test Agent (with Policy)

Tests the insert operation on planetscale_insert_order_v1 data product.
This agent:
1. Creates a decision envelope
2. Evaluates discount_cap_v1 policy
3. Inserts an order using decision_write with operation: "insert"
4. Closes the decision envelope
"""

import os
import sys
import json
from mcp_client import MCPClient


def run_insert_test():
    # Get configuration from environment
    mcp_url = os.getenv('MCP_AGENT_URL', 'https://mcp.tracemem.com')
    api_key = os.getenv('TRACEMEM_API_KEY')
    instance = os.getenv('TRACEMEM_INSTANCE')
    actor = os.getenv('TRACEMEM_ACTOR', 'test-insert-agent')
    
    # Test data - can be overridden via environment variables
    customer_id = int(os.getenv('CUSTOMER_ID', '1001'))
    product_id = int(os.getenv('PRODUCT_ID', '2'))
    quantity = int(os.getenv('QUANTITY', '1'))
    total_amount = float(os.getenv('TOTAL_AMOUNT', '99.99'))
    order_status = os.getenv('ORDER_STATUS', 'pending')
    proposed_discount = float(os.getenv('PROPOSED_DISCOUNT', '0'))
    
    if not api_key:
        print('ERROR: TRACEMEM_API_KEY environment variable is required', file=sys.stderr)
        sys.exit(1)
    
    print('=' * 60)
    print('TraceMem MCP - Insert Test Agent')
    print('=' * 60)
    print()
    print(f'Connecting to Agent MCP at: {mcp_url}')
    if instance:
        print(f'Instance: {instance}')
    print(f'Actor: {actor}')
    print('Order Data:')
    print(f'  Customer ID: {customer_id}')
    print(f'  Product ID: {product_id}')
    print(f'  Quantity: {quantity}')
    print(f'  Total Amount: {total_amount}')
    print(f'  Order Status: {order_status}')
    print(f'  Proposed Discount: {proposed_discount}')
    print()
    
    client = MCPClient(mcp_url, api_key)
    decision_id = None
    
    try:
        # Initialize MCP session
        print('Initializing MCP session...')
        init_result = client.initialize()
        server_name = init_result.get('serverInfo', {}).get('name', 'TraceMem Agent MCP')
        print(f'✓ Connected to {server_name}')
        print()
        
        # Step 1: Create decision envelope
        print('Step 1: Creating decision envelope...')
        decision = client.call_tool('decision_create', {
            'intent': 'test.insert.order',
            'automation_mode': 'autonomous',
            'instance': instance,
            'actor': actor,
            'metadata': {
                'customer_id': str(customer_id),
                'product_id': str(product_id),
                'test_type': 'insert',
            },
        })
        
        decision_id = decision.get('decision_id') or decision.get('id')
        if not decision_id:
            raise Exception('Failed to get decision_id from decision_create response')
        print(f'✓ Decision envelope created: {decision_id}')
        print()
        
        # Step 2: Evaluate policy
        print('Step 2: Evaluating discount_cap_v1 policy...')
        policy_result = client.call_tool('decision_evaluate', {
            'decision_id': decision_id,
            'policy_id': 'discount_cap_v1',
            'inputs': {
                'proposed_discount': proposed_discount,
            },
        })
        
        outcome = policy_result.get('outcome', 'unknown')
        print('✓ Policy evaluation completed')
        print(f'  Policy ID: discount_cap_v1')
        print(f'  Proposed Discount: {proposed_discount}')
        print(f'  Outcome: {outcome}')
        if policy_result.get('rationale'):
            rationale = policy_result['rationale']
            if isinstance(rationale, dict):
                rationale_message = rationale.get('message', json.dumps(rationale))
            else:
                rationale_message = rationale
            print(f'  Rationale: {rationale_message}')
        if policy_result.get('event_id'):
            print(f'  Event ID: {policy_result["event_id"]}')
        print()
        
        # Handle policy outcomes
        if outcome == 'deny':
            raise Exception(f'Policy evaluation denied the operation. Rationale: {policy_result.get("rationale", {}).get("message", "No rationale provided")}')
        elif outcome == 'requires_exception':
            print('⚠ Policy requires exception/approval, but continuing with test...')
            print()
        elif outcome != 'allow':
            print(f'⚠ Unexpected policy outcome: {outcome}, continuing with test...')
            print()
        
        # Step 3: Insert order
        print('Step 3: Inserting order...')
        write_result = client.call_tool('decision_write', {
            'decision_id': decision_id,
            'product': 'planetscale_insert_order_v1',
            'purpose': 'web_order',
            'mutation': {
                'operation': 'insert',
                'records': [{
                    'customer_id': customer_id,
                    'product_id': product_id,
                    'quantity': quantity,
                    'total_amount': total_amount,
                    'order_status': order_status,
                }],
            },
        })
        
        print('✓ Order inserted')
        if write_result.get('event_id'):
            print(f'  Event ID: {write_result["event_id"]}')
        if write_result.get('status'):
            print(f'  Status: {write_result["status"]}')
        if write_result.get('created_records') and len(write_result['created_records']) > 0:
            print(f'  Created {len(write_result["created_records"])} record(s):')
            for index, record in enumerate(write_result['created_records']):
                print(f'  Record {index + 1}:')
                print(json.dumps(record, indent=2))
        if write_result.get('mutation_summary'):
            print(f'  Mutation Summary: {json.dumps(write_result["mutation_summary"])}')
        print()
        
        # Step 4: Close decision (commit)
        print('Step 4: Committing decision...')
        close_result = client.call_tool('decision_close', {
            'decision_id': decision_id,
            'action': 'commit',
        })
        print('✓ Decision committed')
        if close_result.get('status'):
            print(f'  Status: {close_result["status"]}')
        print()
        
        # Summary
        print('=' * 60)
        print('Summary')
        print('=' * 60)
        print(f'Decision ID: {decision_id}')
        print('Result: ✓ Insert operation completed successfully')
        if write_result.get('created_records') and len(write_result['created_records']) > 0:
            first_record = write_result['created_records'][0]
            if first_record.get('order_id'):
                print(f'Created Order ID: {first_record["order_id"]}')
        print()
        
    except Exception as error:
        print(f'✗ Error: {str(error)}', file=sys.stderr)
        import traceback
        traceback.print_exc()
        
        # Try to close decision on error
        if decision_id:
            try:
                print('Attempting to abort decision...')
                client.call_tool('decision_close', {
                    'decision_id': decision_id,
                    'action': 'abort',
                    'reason': f'Error occurred: {str(error)}',
                })
                print('✓ Decision aborted')
            except Exception as close_error:
                print(f'Failed to abort decision: {str(close_error)}', file=sys.stderr)
        
        sys.exit(1)


if __name__ == '__main__':
    run_insert_test()

Environment Variables

  • TRACEMEM_API_KEY (required): Your TraceMem agent API key
  • MCP_AGENT_URL (optional): MCP server URL (default: https://mcp.tracemem.com)
  • TRACEMEM_INSTANCE (optional): Instance identifier
  • TRACEMEM_ACTOR (optional): Actor identifier (default: test-insert-agent)
  • CUSTOMER_ID (optional): Customer ID for order (default: 1001)
  • PRODUCT_ID (optional): Product ID for order (default: 2)
  • QUANTITY (optional): Order quantity (default: 1)
  • TOTAL_AMOUNT (optional): Order total amount (default: 99.99)
  • ORDER_STATUS (optional): Order status (default: pending)
  • PROPOSED_DISCOUNT (optional): Proposed discount for policy evaluation (default: 0)

Example 3: Insert Agent (without Policy)

This example demonstrates inserting an order without policy evaluation.

python
#!/usr/bin/env python3
"""
Insert Test Agent (without Policy)

Tests the insert operation on planetscale_insert_order_no_policy_v1 data product.
This agent:
1. Creates a decision envelope
2. Inserts an order using decision_write with operation: "insert"
3. Closes the decision envelope
"""

import os
import sys
import json
from mcp_client import MCPClient


def run_insert_test():
    # Get configuration from environment
    mcp_url = os.getenv('MCP_AGENT_URL', 'https://mcp.tracemem.com')
    api_key = os.getenv('TRACEMEM_API_KEY')
    instance = os.getenv('TRACEMEM_INSTANCE')
    actor = os.getenv('TRACEMEM_ACTOR', 'test-insert-agent')
    
    # Test data - can be overridden via environment variables
    customer_id = int(os.getenv('CUSTOMER_ID', '1002'))
    product_id = int(os.getenv('PRODUCT_ID', '4'))
    quantity = int(os.getenv('QUANTITY', '1'))
    total_amount = float(os.getenv('TOTAL_AMOUNT', '99.99'))
    order_status = os.getenv('ORDER_STATUS', 'pending')
    
    if not api_key:
        print('ERROR: TRACEMEM_API_KEY environment variable is required', file=sys.stderr)
        sys.exit(1)
    
    print('=' * 60)
    print('TraceMem MCP - Insert Test Agent')
    print('=' * 60)
    print()
    print(f'Connecting to Agent MCP at: {mcp_url}')
    if instance:
        print(f'Instance: {instance}')
    print(f'Actor: {actor}')
    print('Order Data:')
    print(f'  Customer ID: {customer_id}')
    print(f'  Product ID: {product_id}')
    print(f'  Quantity: {quantity}')
    print(f'  Total Amount: {total_amount}')
    print(f'  Order Status: {order_status}')
    print()
    
    client = MCPClient(mcp_url, api_key)
    decision_id = None
    
    try:
        # Initialize MCP session
        print('Initializing MCP session...')
        init_result = client.initialize()
        server_name = init_result.get('serverInfo', {}).get('name', 'TraceMem Agent MCP')
        print(f'✓ Connected to {server_name}')
        print()
        
        # Step 1: Create decision envelope
        print('Step 1: Creating decision envelope...')
        decision = client.call_tool('decision_create', {
            'intent': 'test.insert.order',
            'automation_mode': 'autonomous',
            'instance': instance,
            'actor': actor,
            'metadata': {
                'customer_id': str(customer_id),
                'product_id': str(product_id),
                'test_type': 'insert',
            },
        })
        
        decision_id = decision.get('decision_id') or decision.get('id')
        if not decision_id:
            raise Exception('Failed to get decision_id from decision_create response')
        print(f'✓ Decision envelope created: {decision_id}')
        print()
        
        # Step 2: Insert order
        print('Step 2: Inserting order...')
        write_result = client.call_tool('decision_write', {
            'decision_id': decision_id,
            'product': 'planetscale_insert_order_no_policy_v1',
            'purpose': 'web_order',
            'mutation': {
                'operation': 'insert',
                'records': [{
                    'customer_id': customer_id,
                    'product_id': product_id,
                    'quantity': quantity,
                    'total_amount': total_amount,
                    'order_status': order_status,
                }],
            },
        })
        
        print('✓ Order inserted')
        if write_result.get('event_id'):
            print(f'  Event ID: {write_result["event_id"]}')
        if write_result.get('status'):
            print(f'  Status: {write_result["status"]}')
        if write_result.get('created_records') and len(write_result['created_records']) > 0:
            print(f'  Created {len(write_result["created_records"])} record(s):')
            for index, record in enumerate(write_result['created_records']):
                print(f'  Record {index + 1}:')
                # Display key fields prominently
                if record.get('order_id') is not None:
                    print(f'    Order ID: {record["order_id"]}')
                if record.get('customer_id') is not None:
                    print(f'    Customer ID: {record["customer_id"]}')
                if record.get('product_id') is not None:
                    print(f'    Product ID: {record["product_id"]}')
                if record.get('quantity') is not None:
                    print(f'    Quantity: {record["quantity"]}')
                if record.get('total_amount') is not None:
                    print(f'    Total Amount: {record["total_amount"]}')
                if record.get('order_status') is not None:
                    print(f'    Order Status: {record["order_status"]}')
                if record.get('order_date') is not None:
                    print(f'    Order Date: {record["order_date"]}')
                # Display full record as JSON for complete details
                print('    Full Record:')
                print(json.dumps(record, indent=4))
        else:
            print('  ⚠ No created records returned (check if return_created is enabled)')
        if write_result.get('mutation_summary'):
            print(f'  Mutation Summary: {json.dumps(write_result["mutation_summary"])}')
        print()
        
        # Step 3: Close decision (commit)
        print('Step 3: Committing decision...')
        close_result = client.call_tool('decision_close', {
            'decision_id': decision_id,
            'action': 'commit',
        })
        print('✓ Decision committed')
        if close_result.get('status'):
            print(f'  Status: {close_result["status"]}')
        print()
        
        # Summary
        print('=' * 60)
        print('Summary')
        print('=' * 60)
        print(f'Decision ID: {decision_id}')
        print('Result: ✓ Insert operation completed successfully')
        if write_result.get('created_records') and len(write_result['created_records']) > 0:
            first_record = write_result['created_records'][0]
            print('Created Record:')
            if first_record.get('order_id') is not None:
                print(f'  Order ID: {first_record["order_id"]}')
            if first_record.get('customer_id') is not None:
                print(f'  Customer ID: {first_record["customer_id"]}')
            if first_record.get('product_id') is not None:
                print(f'  Product ID: {first_record["product_id"]}')
            if first_record.get('quantity') is not None:
                print(f'  Quantity: {first_record["quantity"]}')
            if first_record.get('total_amount') is not None:
                print(f'  Total Amount: {first_record["total_amount"]}')
            if first_record.get('order_status') is not None:
                print(f'  Order Status: {first_record["order_status"]}')
            print(f'  Full Record: {json.dumps(first_record, indent=2)}')
        else:
            print('⚠ No created records returned')
        print()
        
    except Exception as error:
        print(f'✗ Error: {str(error)}', file=sys.stderr)
        import traceback
        traceback.print_exc()
        
        # Try to close decision on error
        if decision_id:
            try:
                print('Attempting to abort decision...')
                client.call_tool('decision_close', {
                    'decision_id': decision_id,
                    'action': 'abort',
                    'reason': f'Error occurred: {str(error)}',
                })
                print('✓ Decision aborted')
            except Exception as close_error:
                print(f'Failed to abort decision: {str(close_error)}', file=sys.stderr)
        
        sys.exit(1)


if __name__ == '__main__':
    run_insert_test()

Example 4: Update Agent

This example demonstrates updating product stock.

python
#!/usr/bin/env python3
"""
Update Test Agent

Tests the update operation on planetscale_update_product_stock_v1 data product.
This agent:
1. Creates a decision envelope
2. Updates product stock using decision_write with operation: "update"
3. Closes the decision envelope
"""

import os
import sys
import json
from mcp_client import MCPClient


def run_update_test():
    # Get configuration from environment
    mcp_url = os.getenv('MCP_AGENT_URL', 'https://mcp.tracemem.com')
    api_key = os.getenv('TRACEMEM_API_KEY')
    instance = os.getenv('TRACEMEM_INSTANCE')
    actor = os.getenv('TRACEMEM_ACTOR', 'test-update-agent')
    
    # Test data - can be overridden via environment variables
    product_id = int(os.getenv('PRODUCT_ID', '4'))
    stock_quantity = int(os.getenv('STOCK_QUANTITY', '90'))
    
    if not api_key:
        print('ERROR: TRACEMEM_API_KEY environment variable is required', file=sys.stderr)
        sys.exit(1)
    
    print('=' * 60)
    print('TraceMem MCP - Update Test Agent')
    print('=' * 60)
    print()
    print(f'Connecting to Agent MCP at: {mcp_url}')
    if instance:
        print(f'Instance: {instance}')
    print(f'Actor: {actor}')
    print('Update Data:')
    print(f'  Product ID: {product_id}')
    print(f'  Stock Quantity: {stock_quantity}')
    print()
    
    client = MCPClient(mcp_url, api_key)
    decision_id = None
    
    try:
        # Initialize MCP session
        print('Initializing MCP session...')
        init_result = client.initialize()
        server_name = init_result.get('serverInfo', {}).get('name', 'TraceMem Agent MCP')
        print(f'✓ Connected to {server_name}')
        print()
        
        # Step 1: Create decision envelope
        print('Step 1: Creating decision envelope...')
        decision = client.call_tool('decision_create', {
            'intent': 'test.update.product.stock',
            'automation_mode': 'autonomous',
            'instance': instance,
            'actor': actor,
            'metadata': {
                'product_id': str(product_id),
                'stock_quantity': str(stock_quantity),
                'test_type': 'update',
            },
        })
        
        decision_id = decision.get('decision_id') or decision.get('id')
        if not decision_id:
            raise Exception('Failed to get decision_id from decision_create response')
        print(f'✓ Decision envelope created: {decision_id}')
        print()
        
        # Step 2: Update product stock
        print('Step 2: Updating product stock...')
        write_result = client.call_tool('decision_write', {
            'decision_id': decision_id,
            'product': 'planetscale_update_product_stock_v1',
            'purpose': 'web_order',
            'mutation': {
                'operation': 'update',
                'records': [{
                    'product_id': product_id,  # Key field for identification
                    'stock_quantity': stock_quantity,  # Field to update
                }],
            },
        })
        
        print('✓ Product stock updated')
        if write_result.get('event_id'):
            print(f'  Event ID: {write_result["event_id"]}')
        if write_result.get('status'):
            print(f'  Status: {write_result["status"]}')
        if write_result.get('mutation_summary'):
            print(f'  Mutation Summary: {json.dumps(write_result["mutation_summary"])}')
        print()
        
        # Step 3: Close decision (commit)
        print('Step 3: Committing decision...')
        close_result = client.call_tool('decision_close', {
            'decision_id': decision_id,
            'action': 'commit',
        })
        print('✓ Decision committed')
        if close_result.get('status'):
            print(f'  Status: {close_result["status"]}')
        print()
        
        # Summary
        print('=' * 60)
        print('Summary')
        print('=' * 60)
        print(f'Decision ID: {decision_id}')
        print('Result: ✓ Update operation completed successfully')
        print(f'Product ID: {product_id}')
        print(f'New Stock Quantity: {stock_quantity}')
        print()
        
    except Exception as error:
        print(f'✗ Error: {str(error)}', file=sys.stderr)
        import traceback
        traceback.print_exc()
        
        # Try to close decision on error
        if decision_id:
            try:
                print('Attempting to abort decision...')
                client.call_tool('decision_close', {
                    'decision_id': decision_id,
                    'action': 'abort',
                    'reason': f'Error occurred: {str(error)}',
                })
                print('✓ Decision aborted')
            except Exception as close_error:
                print(f'Failed to abort decision: {str(close_error)}', file=sys.stderr)
        
        sys.exit(1)


if __name__ == '__main__':
    run_update_test()

Environment Variables

  • TRACEMEM_API_KEY (required): Your TraceMem agent API key
  • MCP_AGENT_URL (optional): MCP server URL (default: https://mcp.tracemem.com)
  • TRACEMEM_INSTANCE (optional): Instance identifier
  • TRACEMEM_ACTOR (optional): Actor identifier (default: test-update-agent)
  • PRODUCT_ID (optional): Product ID to update (default: 4)
  • STOCK_QUANTITY (optional): New stock quantity (default: 90)

Example 5: Delete Agent

This example demonstrates deleting a target record.

python
#!/usr/bin/env python3
"""
Delete Test Agent

Tests the delete operation on planetscale_delete_target_v1 data product.
This agent:
1. Creates a decision envelope
2. Deletes a target record using decision_write with operation: "delete"
3. Closes the decision envelope
"""

import os
import sys
import json
import re
from mcp_client import MCPClient


def run_delete_test():
    # Get configuration from environment
    mcp_url = os.getenv('MCP_AGENT_URL', 'https://mcp.tracemem.com')
    api_key = os.getenv('TRACEMEM_API_KEY')
    instance = os.getenv('TRACEMEM_INSTANCE')
    actor = os.getenv('TRACEMEM_ACTOR', 'test-delete-agent')
    
    # Test data - target ID must be a UUID
    target_id = os.getenv('TARGET_ID', '0cf1e19e-00ed-4a4c-8d82-ee70f590fad8')
    
    if not api_key:
        print('ERROR: TRACEMEM_API_KEY environment variable is required', file=sys.stderr)
        sys.exit(1)
    
    if not target_id:
        print('ERROR: TARGET_ID environment variable is required (must be a UUID)', file=sys.stderr)
        print('Example: TARGET_ID=550e8400-e29b-41d4-a716-446655440000', file=sys.stderr)
        sys.exit(1)
    
    # Basic UUID format validation
    uuid_regex = re.compile(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$', re.IGNORECASE)
    if not uuid_regex.match(target_id):
        print('ERROR: TARGET_ID must be a valid UUID format', file=sys.stderr)
        print(f'Received: {target_id}', file=sys.stderr)
        print('Expected format: 550e8400-e29b-41d4-a716-446655440000', file=sys.stderr)
        sys.exit(1)
    
    print('=' * 60)
    print('TraceMem MCP - Delete Test Agent')
    print('=' * 60)
    print()
    print(f'Connecting to Agent MCP at: {mcp_url}')
    if instance:
        print(f'Instance: {instance}')
    print(f'Actor: {actor}')
    print('Delete Data:')
    print(f'  Target ID: {target_id}')
    print()
    print('⚠ WARNING: This will delete a record from the database!')
    print()
    
    client = MCPClient(mcp_url, api_key)
    decision_id = None
    
    try:
        # Initialize MCP session
        print('Initializing MCP session...')
        init_result = client.initialize()
        server_name = init_result.get('serverInfo', {}).get('name', 'TraceMem Agent MCP')
        print(f'✓ Connected to {server_name}')
        print()
        
        # Step 1: Create decision envelope
        print('Step 1: Creating decision envelope...')
        decision = client.call_tool('decision_create', {
            'intent': 'test.delete.target',
            'automation_mode': 'autonomous',
            'instance': instance,
            'actor': actor,
            'metadata': {
                'target_id': target_id,
                'test_type': 'delete',
            },
        })
        
        decision_id = decision.get('decision_id') or decision.get('id')
        if not decision_id:
            raise Exception('Failed to get decision_id from decision_create response')
        print(f'✓ Decision envelope created: {decision_id}')
        print()
        
        # Step 2: Delete target record
        print('Step 2: Deleting target record...')
        write_result = client.call_tool('decision_write', {
            'decision_id': decision_id,
            'product': 'planetscale_delete_target_v1',
            'purpose': 'delete_target',
            'mutation': {
                'operation': 'delete',
                'records': [{
                    'id': target_id,  # Key field for deletion
                }],
            },
        })
        
        print('✓ Target record deleted')
        if write_result.get('event_id'):
            print(f'  Event ID: {write_result["event_id"]}')
        if write_result.get('status'):
            print(f'  Status: {write_result["status"]}')
        if write_result.get('mutation_summary'):
            print(f'  Mutation Summary: {json.dumps(write_result["mutation_summary"])}')
        print()
        
        # Step 3: Close decision (commit)
        print('Step 3: Committing decision...')
        close_result = client.call_tool('decision_close', {
            'decision_id': decision_id,
            'action': 'commit',
        })
        print('✓ Decision committed')
        if close_result.get('status'):
            print(f'  Status: {close_result["status"]}')
        print()
        
        # Summary
        print('=' * 60)
        print('Summary')
        print('=' * 60)
        print(f'Decision ID: {decision_id}')
        print('Result: ✓ Delete operation completed successfully')
        print(f'Deleted Target ID: {target_id}')
        print()
        
    except Exception as error:
        print(f'✗ Error: {str(error)}', file=sys.stderr)
        import traceback
        traceback.print_exc()
        
        # Try to close decision on error
        if decision_id:
            try:
                print('Attempting to abort decision...')
                client.call_tool('decision_close', {
                    'decision_id': decision_id,
                    'action': 'abort',
                    'reason': f'Error occurred: {str(error)}',
                })
                print('✓ Decision aborted')
            except Exception as close_error:
                print(f'Failed to abort decision: {str(close_error)}', file=sys.stderr)
        
        sys.exit(1)


if __name__ == '__main__':
    run_delete_test()

Environment Variables

  • TRACEMEM_API_KEY (required): Your TraceMem agent API key
  • MCP_AGENT_URL (optional): MCP server URL (default: https://mcp.tracemem.com)
  • TRACEMEM_INSTANCE (optional): Instance identifier
  • TRACEMEM_ACTOR (optional): Actor identifier (default: test-delete-agent)
  • TARGET_ID (required): UUID of target record to delete

Common Patterns

Error Handling Best Practices

Always ensure decision envelopes are properly closed, even on errors:

python
decision_id = None
try:
    # Create decision and perform operations
    decision = client.call_tool('decision_create', {...})
    decision_id = decision.get('decision_id')
    
    # Perform operations...
    
    # Commit on success
    client.call_tool('decision_close', {
        'decision_id': decision_id,
        'action': 'commit',
    })
except Exception as error:
    # Always abort on error
    if decision_id:
        try:
            client.call_tool('decision_close', {
                'decision_id': decision_id,
                'action': 'abort',
                'reason': f'Error occurred: {str(error)}',
            })
        except Exception:
            pass  # Log but don't fail on abort failure
    raise

Decision Envelope Lifecycle

Every agent operation should follow this pattern:

  1. Initialize MCP Session: Connect to the Agent MCP server
  2. Create Decision Envelope: Open a decision with appropriate intent
  3. Perform Operations: Read, write, evaluate policies, etc.
  4. Close Decision: Commit on success, abort on error

Environment Variable Configuration

All examples use environment variables for configuration:

bash
# Required
export TRACEMEM_API_KEY="your-api-key"

# Optional
export MCP_AGENT_URL="https://mcp.tracemem.com"
export TRACEMEM_INSTANCE="my-instance"
export TRACEMEM_ACTOR="my-agent"

Testing Tips

  1. Start with Read Operations: Test read operations first to verify connectivity
  2. Use Test Data: Use non-production data products for testing
  3. Check Decision Traces: Review decision traces in the TraceMem dashboard
  4. Handle Errors Gracefully: Always implement proper error handling and decision cleanup

TraceMem is trace-native infrastructure for AI agents