Provenance Tracking
Provenance tracking in Agent Tool Protocol allows you to track where data comes from, where it goes, and enforce security policies on data flow. This is essential for compliance, security auditing, and preventing data leakage.
What is Provenance?
Provenance is metadata that tracks the origin and history of data as it flows through your system. Every piece of data can carry information about:
- Source: Where the data originated (API call, user input, LLM response)
- Operations: What operations have been performed on it
- Recipients: Where the data has been sent
- Permissions: Who can read or modify the data
Enabling Provenance Tracking
Basic Tracking
import { createServer, ProvenanceMode } from '@mondaydotcomorg/atp-server';
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.TRACK, // Enable tracking
},
});
Provenance Modes
enum ProvenanceMode {
NONE = 'none', // No tracking (default, best performance)
TRACK = 'track', // Track provenance (recommended)
ENFORCE = 'enforce', // Track + enforce policies
}
How Provenance Works
Automatic Tracking
When provenance is enabled, every API call automatically tracks data origin:
// Code executed in sandbox
const user = await users.getUser({ userId: '123' });
// user object now has hidden provenance metadata:
// {
// source: {
// type: 'api',
// api: 'users',
// function: 'getUser',
// timestamp: 1234567890,
// },
// operations: [],
// recipients: [],
// }
Provenance Inheritance
Data derived from tracked data inherits provenance:
const user = await users.getUser({ userId: '123' });
// user has provenance
const name = user.name;
// name inherits provenance from user
const greeting = `Hello, ${name}`;
// greeting inherits provenance
await llm.call({ prompt: greeting });
// Provenance system knows that user data is being sent to LLM
Manual Provenance Access
You can access provenance metadata directly:
import { getProvenance, hasProvenance } from '@mondaydotcomorg/atp-provenance';
const user = await users.getUser({ userId: '123' });
if (hasProvenance(user)) {
const provenance = getProvenance(user);
console.log('Data source:', provenance.source);
console.log('Operations:', provenance.operations);
console.log('Recipients:', provenance.recipients);
}
Security Policies
Built-in Policies
Agent Tool Protocol provides several built-in security policies:
1. Prevent Data Exfiltration
Block sensitive data from leaving your system:
import { preventDataExfiltration } from '@mondaydotcomorg/atp-server';
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.ENFORCE,
securityPolicies: [
preventDataExfiltration({
// Block data from these sources
sources: [
'users.getUser',
'payments.getTransaction',
'secrets.getAPIKey',
],
// From being sent to these recipients
recipients: [
'external-api',
'logging',
],
}),
],
},
});
Now if code tries to exfiltrate data:
// This will throw a SecurityViolation error
const user = await users.getUser({ userId: '123' });
await externalApi.sendData({ data: user }); // ❌ BLOCKED!
2. Require User Origin
Ensure data comes from user input, not LLMs:
import { requireUserOrigin } from '@mondaydotcomorg/atp-server';
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.ENFORCE,
securityPolicies: [
requireUserOrigin({
// These APIs require user-originated data
apis: ['payments.makePayment', 'users.deleteUser'],
}),
],
},
});
Usage:
// This is OK - data comes from user input
const amount = getUserInput(); // User provides amount
await payments.makePayment({ amount }); // ✅ ALLOWED
// This is BLOCKED - data comes from LLM
const llmSuggestion = await llm.call({ prompt: "How much should I pay?" });
await payments.makePayment({ amount: llmSuggestion }); // ❌ BLOCKED!
3. Block LLM Recipients
Prevent sensitive data from reaching LLMs:
import { blockLLMRecipients } from '@mondaydotcomorg/atp-server';
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.ENFORCE,
securityPolicies: [
blockLLMRecipients({
// Block data from these sources
sources: [
'users.getCreditCard',
'users.getSSN',
'secrets.getAPIKey',
],
}),
],
},
});
Usage:
// This will throw a SecurityViolation error
const creditCard = await users.getCreditCard({ userId: '123' });
await llm.call({ prompt: `Process payment: ${creditCard}` }); // ❌ BLOCKED!
4. Audit Sensitive Access
Log access to sensitive data without blocking:
import { auditSensitiveAccess } from '@mondaydotcomorg/atp-server';
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.TRACK,
securityPolicies: [
auditSensitiveAccess({
sources: ['users.getUser', 'payments.getTransaction'],
logger: (event) => {
console.log('Sensitive data accessed:', {
source: event.source,
recipient: event.recipient,
timestamp: event.timestamp,
executionId: event.executionId,
});
// Send to audit log service
auditService.log(event);
},
}),
],
},
});
Policies with Approval
All policies support approval mode, which pauses execution for human approval:
import { preventDataExfiltrationWithApproval } from '@mondaydotcomorg/atp-server';
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.ENFORCE,
securityPolicies: [
preventDataExfiltrationWithApproval({
sources: ['users.getUser'],
recipients: ['external-api'],
}),
],
},
});
When data exfiltration is detected:
// Execution pauses for approval
const user = await users.getUser({ userId: '123' });
await externalApi.sendData({ data: user }); // ⏸️ PAUSED FOR APPROVAL
// Client receives approval request
const result = await client.execute(code);
if (result.needsCallback?.type === 'approval') {
const approved = await showUserApprovalDialog(
result.needsCallback.payload.message
);
// Resume with approval result
await client.resume(result.executionId, { approved });
}
Custom Security Policies
Creating Custom Policies
You can create custom security policies:
import { createCustomPolicy } from '@mondaydotcomorg/atp-server';
const customPolicy = createCustomPolicy({
name: 'prevent-pii-logging',
description: 'Prevent PII from being logged',
// Called for every data operation
evaluate: (context) => {
const { source, recipient, data, provenance } = context;
// Check if data contains PII
const isPII = source?.api === 'users' &&
(source.function === 'getUser' ||
source.function === 'getUserProfile');
// Check if recipient is logging
const isLogging = recipient?.type === 'log';
if (isPII && isLogging) {
return {
action: 'deny',
reason: 'PII data cannot be logged',
};
}
return { action: 'allow' };
},
});
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.ENFORCE,
securityPolicies: [customPolicy],
},
});
Advanced Policy Example
const gdprCompliancePolicy = createCustomPolicy({
name: 'gdpr-compliance',
description: 'Enforce GDPR compliance rules',
evaluate: (context) => {
const { source, recipient, data, provenance } = context;
// Check if data is EU user data
const isEUUserData = provenance?.tags?.includes('eu-user-data');
// Check if recipient is outside EU
const isNonEURecipient = recipient?.tags?.includes('non-eu-system');
if (isEUUserData && isNonEURecipient) {
// Check for user consent
const hasConsent = provenance?.metadata?.consent === true;
if (!hasConsent) {
return {
action: 'deny',
reason: 'EU user data cannot be transferred outside EU without consent',
suggestion: 'Obtain user consent first',
};
}
}
// Check data retention policies
const retentionDays = provenance?.metadata?.retentionDays || 90;
const dataAge = Date.now() - provenance.timestamp;
const maxAge = retentionDays * 24 * 60 * 60 * 1000;
if (dataAge > maxAge) {
return {
action: 'deny',
reason: `Data retention period exceeded (${retentionDays} days)`,
};
}
return { action: 'allow' };
},
});
Tagging Data
Adding Tags
You can add custom tags to provenance metadata:
server.registerAPI('users', {
getEUUser: {
description: 'Get EU user data',
inputSchema: { /* ... */ },
handler: async ({ userId }) => {
const user = await database.users.findOne({ userId });
// Mark data with custom tags
return markWithProvenance(user, {
tags: ['eu-user-data', 'pii', 'gdpr-protected'],
metadata: {
retentionDays: 90,
consentRequired: true,
},
});
},
},
});
Using Tags in Policies
const policy = createCustomPolicy({
name: 'tag-based-policy',
evaluate: (context) => {
const { provenance } = context;
// Block operations on data with specific tags
if (provenance?.tags?.includes('confidential')) {
return {
action: 'deny',
reason: 'Confidential data cannot be processed',
};
}
return { action: 'allow' };
},
});
Reader Permissions
Control who can read data:
import { markWithProvenance } from '@mondaydotcomorg/atp-provenance';
const sensitiveData = {
secret: 'my-secret',
};
// Only admin role can read this data
const protectedData = markWithProvenance(sensitiveData, {
readerPermissions: {
roles: ['admin'],
users: ['user-123'],
},
});
// Later, when code tries to read this data:
// The policy engine checks if current user has permission
Provenance State Management
Capturing State
Capture provenance state for later restoration:
import { captureProvenanceState, restoreProvenanceState } from '@mondaydotcomorg/atp-provenance';
// Capture current provenance state
const state = captureProvenanceState();
// Perform operations that modify provenance
const user = await users.getUser({ userId: '123' });
// Restore previous state
restoreProvenanceState(state);
Execution Cleanup
Provenance data is automatically cleaned up after execution:
// After each execution, provenance data is cleared
// This prevents memory leaks and ensures isolation
Best Practices
1. Choose the Right Mode
// Development: TRACK mode for debugging
const devServer = createServer({
execution: {
provenanceMode: ProvenanceMode.TRACK,
},
});
// Production: ENFORCE mode for security
const prodServer = createServer({
execution: {
provenanceMode: ProvenanceMode.ENFORCE,
securityPolicies: [
preventDataExfiltration(/* ... */),
blockLLMRecipients(/* ... */),
],
},
});
2. Layer Security Policies
Use multiple policies for defense-in-depth:
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.ENFORCE,
securityPolicies: [
// Layer 1: Prevent data exfiltration
preventDataExfiltration({
sources: ['users.*', 'payments.*'],
recipients: ['external-*'],
}),
// Layer 2: Block LLM access to sensitive data
blockLLMRecipients({
sources: ['secrets.*', 'auth.*'],
}),
// Layer 3: Require user origin for sensitive operations
requireUserOrigin({
apis: ['payments.makePayment', 'users.deleteUser'],
}),
// Layer 4: Audit all access
auditSensitiveAccess({
sources: ['*'],
logger: auditLogger,
}),
],
},
});
3. Tag Sensitive Data
Always tag sensitive data at the source:
server.registerAPI('database', {
getUserCreditCard: {
description: 'Get user credit card',
handler: async ({ userId }) => {
const card = await db.creditCards.findOne({ userId });
return markWithProvenance(card, {
tags: ['pii', 'financial', 'pci-dss'],
sensitivityLevel: 'high',
retentionDays: 7,
});
},
},
});
4. Use Approval for High-Risk Operations
// Allow high-risk operations with approval
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.ENFORCE,
securityPolicies: [
requireUserOriginWithApproval({
apis: ['payments.makePayment'],
}),
],
},
});
5. Monitor and Alert
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.ENFORCE,
securityPolicies: [
auditSensitiveAccess({
sources: ['users.getUser'],
logger: (event) => {
// Alert on suspicious patterns
if (event.source.executionCount > 100) {
alertSecurityTeam('Potential data scraping detected', event);
}
// Log to SIEM
siemService.log(event);
},
}),
],
},
});
Performance Considerations
Impact of Provenance Tracking
| Mode | Performance Impact | Use Case |
|---|---|---|
| NONE | None (0%) | Development, non-sensitive data |
| TRACK | Low (5-10%) | Production with auditing |
| ENFORCE | Medium (10-20%) | Production with active security |
Optimization Tips
- Use NONE mode in development if not testing security
- Cache provenance checks for repeated operations
- Batch provenance operations when possible
- Use specific source patterns instead of wildcards
Debugging Provenance
Enable Debug Logging
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.TRACK,
},
logger: 'debug',
});
Inspect Provenance in Code
import { getAllProvenance } from '@mondaydotcomorg/atp-provenance';
// Get all provenance metadata for debugging
const allProvenance = getAllProvenance();
console.log('Provenance graph:', allProvenance);
Next Steps
- Security Policies: Deep dive into policy creation
- Data Exfiltration Prevention: Advanced exfiltration prevention
- Tool Metadata: Annotate tools with security metadata
- OAuth Scopes: Scope-based access control
Common Use Cases
1. Preventing Credit Card Leakage
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.ENFORCE,
securityPolicies: [
blockLLMRecipients({
sources: ['payments.getCreditCard'],
}),
preventDataExfiltration({
sources: ['payments.getCreditCard'],
recipients: ['external-*', 'logging.*'],
}),
],
},
});
2. GDPR Compliance
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.ENFORCE,
securityPolicies: [
gdprCompliancePolicy, // Custom policy (see above)
auditSensitiveAccess({
sources: ['users.*'],
logger: gdprAuditLogger,
}),
],
},
});
3. PCI-DSS Compliance
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.ENFORCE,
securityPolicies: [
preventDataExfiltration({
sources: ['payments.*'],
recipients: ['external-*'],
}),
requireUserOriginWithApproval({
apis: ['payments.makePayment'],
}),
auditSensitiveAccess({
sources: ['payments.*'],
logger: pciAuditLogger,
}),
],
},
});