@tracemem/opencode-plugin
v0.2.1
Published
OpenCode plugin for TraceMem decision tracking and traceability
Downloads
398
Maintainers
Readme
@tracemem/opencode-plugin
OpenCode plugin for TraceMem decision tracking and traceability. This plugin provides tools to create, manage, and track decisions through the TraceMem MCP API.
Install
Add the plugin to your opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["@tracemem/opencode-plugin"]
}OpenCode will automatically install the plugin and its dependencies on startup.
Configure
Required Environment Variable
Set your TraceMem API key:
export TRACEMEM_API_KEY=your_api_key_hereOr add it to your .env file in your project root.
Optional Environment Variable
Override the default MCP server URL (default: https://mcp.tracemem.com):
export TRACEMEM_MCP_URL=https://mcp.tracemem.comVerify
After installation, verify your setup by asking OpenCode to run:
tracemem_doctorThis will check your API key configuration and test connectivity to the TraceMem MCP server.
Understanding the Workflow
⚠️ CRITICAL: Decision Envelope is MANDATORY
ALL TraceMem operations MUST happen within a decision envelope. This is not optional.
Operations that REQUIRE a decision envelope:
- ✅
tracemem_decision_read- read data - ✅
tracemem_decision_write- insert/update/delete data - ✅
tracemem_decision_evaluate- evaluate policies - ✅
tracemem_decision_request_approval- request approvals
Operations that DO NOT require a decision envelope (discovery tools):
- ❌
tracemem_products_list- list available products - ❌
tracemem_product_get- get product schema
Attempting any governed operation without a decision envelope will fail with an error.
Core MCP Methods vs Convenience Tools
OpenCode Convenience Tools (plugin-specific):
tracemem_open→ Wrapper fordecision_createwith action-to-intent mappingtracemem_note→ Wrapper fordecision_add_contextwith sanitization
Core MCP Tools (always available):
decision_create,decision_read,decision_write,decision_evaluatedecision_request_approval,decision_closeproducts_list,product_get
Important: Even when using convenience tools like tracemem_open, the same rules apply - ALL operations must occur within the decision envelope created by that call.
What Happens Without a Decision Envelope?
// ❌ WRONG - This will FAIL
await tracemem_decision_read({
product: "customers_v1",
purpose: "support_context",
query: {customer_id: 1001}
});
// Error: "decision_id is required"
// ✓ CORRECT - Create decision first
await tracemem_open({action: "db_change"});
await tracemem_decision_read({
product: "customers_v1",
purpose: "support_context",
query: {customer_id: 1001}
});Usage
Recommended Pattern
IMPORTANT: ALL operations shown below MUST occur within the decision envelope created in step 1.
The recommended workflow for using TraceMem with OpenCode:
Open a decision before starting work (MANDATORY FIRST STEP):
tracemem_open(action="refactor")→ Returns
decision_idwhich is automatically saved for subsequent operationsGet product metadata before reading/writing (recommended):
tracemem_product_get(product="customers_v1")→ Returns METADATA: schema with field names, allowed_purposes, example queries → Does NOT require decision_id → Does NOT return actual data - just information ABOUT the product
Add context as you work:
tracemem_note(kind="info", message="Starting refactoring of user service")→ Uses decision_id from step 1
Read actual data when needed (REQUIRES decision_id from step 1):
tracemem_decision_read(product="customers_v1", purpose="order_validation", query={"customer_id": "1001"})→ Returns ACTUAL DATA: records array with real customer/order/etc data from database → Uses decision_id from step 1 → Use field names from metadata (step 2) → Use purpose from allowed_purposes (step 2)
Evaluate a policy (REQUIRES decision_id from step 1):
tracemem_decision_evaluate(policy_id="discount_cap_v1", inputs={"proposed_discount": 0.15, "customer_tier": "premium"})Request approval if needed (REQUIRES decision_id from step 1):
tracemem_decision_request_approval(title="Discount Approval", message="Customer requesting 25% discount")Write data - insert, update, or delete (REQUIRES decision_id from step 1):
// INSERT - create new record tracemem_decision_write(product="orders_v1", purpose="order_creation", mutation={ operation: "insert", records: [{customer_id: 1001, total_amount: 99.99}] }) // UPDATE - modify existing record tracemem_decision_write(product="orders_v1", purpose="order_update", mutation={ operation: "update", filter: {order_id: 12345}, data: {status: "shipped"} }) // DELETE - remove record tracemem_decision_write(product="orders_v1", purpose="data_cleanup", mutation={ operation: "delete", filter: {order_id: 67890} })Close the decision when done (MANDATORY FINAL STEP):
tracemem_decision_close(action="commit", reason="Order successfully processed")→ Use "commit" for successful operations → Use "abort" for cancelled/failed operations
Data Flow
Step 1: tracemem_open
↓ (returns decision_id, saved automatically)
Step 2-7: All operations use the decision_id
- tracemem_decision_read
- tracemem_decision_write
- tracemem_decision_evaluate
- tracemem_decision_request_approval
Step 8: tracemem_decision_close (uses decision_id)Auto-Intent Mapping
The tracemem_open tool automatically maps common actions to standardized intents:
| Action | Intent |
|--------|--------|
| edit_files | code.change.apply |
| refactor | code.refactor.execute |
| run_command | ops.command.execute |
| deploy | deploy.release.execute |
| secrets | secrets.change.propose |
| db_change | data.change.apply |
| review | code.review.assist |
Example:
tracemem_open(action="refactor")
// Automatically maps to intent: code.refactor.executeAvailable Tools
Core Tools
tracemem_capabilities_get- Get MCP server capabilitiestracemem_doctor- Verify plugin setup and connection
Product Tools
tracemem_products_list- List all productstracemem_product_get- Get product details
Decision Tools
tracemem_open- Open a new decision with auto-intent mappingtracemem_decision_create- Create a new decisiontracemem_decision_get- Get decision detailstracemem_decision_add_context- Add context to a decisiontracemem_decision_read- Read data through a governed data producttracemem_decision_evaluate- Evaluate a policy within a decision contexttracemem_decision_request_approval- Request approvaltracemem_decision_write- Write mutation to decisiontracemem_decision_trace- Get trace informationtracemem_decision_receipt- Get decision receipttracemem_decision_close- Close a decision
Safe Utilities
tracemem_note- Add a safe note (automatically sanitized)
State Management
The plugin maintains the current decision ID in memory. If you omit the decision_id parameter from decision tools, they will use the most recently created decision (from tracemem_open or tracemem_decision_create).
Troubleshooting
Error: "decision_id is required"
Cause: You attempted a governed operation without first creating a decision envelope.
Solution: Always call tracemem_open or decision_create FIRST:
// ❌ WRONG
await tracemem_decision_read({product: "customers_v1", ...});
// ✓ CORRECT
await tracemem_open({action: "db_change"});
await tracemem_decision_read({product: "customers_v1", ...});Error: "invalid automation_mode: manual" (or auto, full_auto, etc.)
Cause: Used an invalid automation mode value.
Valid values (ONLY these 4):
propose- suggest actions, human decidesapprove- execute after approvaloverride- human overrides policyautonomous- fully automated
Solution: Use one of the 4 valid values:
// ❌ WRONG
await decision_create({
intent: "order.create",
automation_mode: "manual" // Invalid!
});
// ✓ CORRECT
await decision_create({
intent: "order.create",
automation_mode: "autonomous" // Valid
});
// Or use tracemem_open which sets automation_mode automatically
await tracemem_open({action: "db_change"});Error: "Purpose 'X' is not allowed for this data product"
Cause: You used a purpose that's not in the product's allowed_purposes list.
Solution: Check allowed purposes FIRST using tracemem_product_get:
// Step 1: Get product info
const product = await tracemem_product_get({product: "customers_v1"});
console.log(product.allowed_purposes);
// Output: ["support_context", "order_validation", "incident_context"]
// Step 2: Use a valid purpose
await tracemem_decision_read({
product: "customers_v1",
purpose: "support_context", // ✓ Valid - from the list
query: {customer_id: 1001}
});Error: "field 'customerId' not found in schema"
Cause: Used incorrect field name in query (wrong capitalization or spelling).
Solution: Check product metadata FIRST using tracemem_product_get:
// Step 1: Get product METADATA (not data)
const product = await tracemem_product_get({product: "customers_v1"});
console.log(product.exposed_schema);
// Output: [
// {name: "customer_id", type: "integer"}, ← Correct field name
// {name: "name", type: "string"},
// ...
// ]
// Step 2: Use exact field names from metadata in your query
await tracemem_decision_read({
product: "customers_v1",
purpose: "support_context",
query: {customer_id: 1001} // ✓ Correct - matches schema
});Remember:
product_get→ Returns METADATA (schema, purposes) - tells you HOW to use the productdecision_read→ Returns ACTUAL DATA (records) - gives you the real data
Error: "Data product 'X' not found or not accessible"
Cause: Product doesn't exist, is not published, or agent doesn't have access.
Solution: List available products first:
// Check what products are available
const products = await tracemem_products_list();
console.log(products);
// Use an existing product name
await tracemem_decision_read({
product: "customers_v1", // ✓ Use exact name from list
...
});Best Practice Checklist
Before performing any data operation:
- ✅ Create decision envelope -
tracemem_openordecision_create - ✅ Get product metadata -
tracemem_product_getto understand structure (schema, purposes) - ✅ Construct operations correctly:
- Use exact field names from metadata
- Choose correct write operation:
insert(new),update(modify existing),delete(remove)
- ✅ Use valid purpose - Choose from
allowed_purposeslist - ✅ Close decision - Always call
tracemem_decision_closewhen done
Security
Secret Redaction
The plugin automatically sanitizes data to prevent secrets from being stored:
- Redacted keys: Any key matching patterns like
token,secret,password,api_key,auth,credential, etc. will have their values replaced with[redacted] - Size limits: Long strings (>1000 chars) are truncated, arrays are limited to 100 items, and recursion depth is limited to 10 levels
- Applied to:
decision_create.metadatadecision_add_context.datadecision_read.querydecision_write.mutation
Best Practices
- Never include secrets in metadata or notes - Even though redaction helps, it's better to avoid including secrets entirely
- Use
tracemem_notefor safe notes - This tool provides additional safety guarantees - Review before closing - Always review decision data before closing with
commit - Use appropriate actions - Use
abortwhen work shouldn't proceed,commitwhen successful
Examples
See the examples/ directory for:
opencode.json- Example OpenCode configurationenv.example- Example environment variable configuration
License
Apache-2.0
Repository
https://github.com/tracemem/tracemem-opencode-plugin
