MCP Tools Reference
Complete reference for all 5 Model Context Protocol (MCP) tools available in AuditSwarm.
Overview
AuditSwarm provides 5 MCP tools that AI agents use to interact with the platform:
| Tool | Purpose | Write Access |
|---|---|---|
suggest_change | Create, update, delete entities | Suggestions only |
query_data | Query entities and data | Read-only |
get_current_context | Get user's current page context | Read-only |
help | Get workflow guidance | Read-only |
upload_document_for_archival | Upload documents for archival | Direct (but creates suggestion) |
Note: Most tools follow the suggestions pattern - AI agents can only create suggestions, not modify production data directly. The upload_document_for_archival tool uploads files to GCP Storage but still requires user approval via a suggestion before the artifact is updated.
1. suggest_change
Universal CRUD operations for all entity types via suggestions.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
entityType | string | Yes | Entity type: audit, issue, risk, control, artifact, workflow, dashboard |
operation | string | Yes | Operation: create, update, delete, approve_with_archival |
entityId | string | Conditional | Required for update and delete, omit for create |
suggestedData | object | Yes | JSON object with entity data (see Suggested Data Fields) |
agentMetadata | object | No | Agent info (name, platform, model, specialization) |
Suggested Data Fields
The suggestedData object contains the actual changes being suggested. The fields depend on the entityType:
For audits:
{
"title": "Q1 2025 SOC2 Review",
"description": "Quarterly SOC2 Type II compliance audit",
"status": "PLANNING", // Query CustomList first!
"type": "COMPLIANCE", // Query CustomList first!
"startDate": "2025-01-15",
"endDate": "2025-02-15",
"budgetHours": 120.0
}
For issues:
{
"title": "Missing MFA on admin accounts",
"description": "Admin users can login without MFA",
"severity": "HIGH", // Query CustomList first!
"status": "OPEN", // Query CustomList first!
"dueDate": "2025-02-01"
}
For risks:
{
"name": "Data Breach via SQL Injection",
"description": "User input not sanitized in search queries",
"severity": "CRITICAL", // Query CustomList first!
"likelihood": "MEDIUM", // Query CustomList first!
"status": "IDENTIFIED" // Query CustomList first!
}
For controls:
{
"name": "MFA Enforcement Policy",
"description": "All users must use multi-factor authentication",
"type": "PREVENTIVE", // Query CustomList first!
"frequency": "CONTINUOUS", // Query CustomList first!
"status": "IMPLEMENTED" // Query CustomList first!
}
For workflows:
{
"name": "SOC2 Evidence Collection",
"description": "Collect all required SOC2 evidence",
"status": "IN_PROGRESS" // Query CustomList first!
}
For dashboards:
{
"name": "Executive Risk Dashboard",
"description": "High-level risk overview for executives",
"visibility": "PRIVATE"
}
For artifact_approval (special operation):
{
"workflowId": "workflow_123",
"workflowName": "SOC2 Compliance",
"artifactId": "artifact_456",
"artifactName": "Risk Assessment",
"documentVersionId": "docver_789",
"documentVersion": {
"fileName": "risk-assessment-2024.pdf",
"gcpStorageUrl": "https://storage.googleapis.com/..."
}
}
Agent Metadata Fields
The agentMetadata object provides context about the AI agent:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | User-friendly agent name (e.g., "SOC2 Auditor") |
platform | string | No | AI platform: claude, chatgpt, copilot, custom |
model | string | No | Model name (e.g., "gpt-4", "claude-3-opus") |
specialization | string | No | Agent's area of focus (e.g., "compliance", "security") |
Example: Create Audit
{
"tool": "suggest_change",
"arguments": {
"entityType": "audit",
"operation": "create",
"suggestedData": {
"title": "Q1 2025 SOC2 Review",
"description": "Quarterly SOC2 Type II compliance audit",
"status": "PLANNING",
"startDate": "2025-01-15",
"dueDate": "2025-02-15"
},
"agentMetadata": {
"name": "SOC2 Auditor",
"platform": "chatgpt",
"model": "gpt-4",
"specialization": "compliance"
}
}
}
Example: Update Risk
{
"tool": "suggest_change",
"arguments": {
"entityType": "risk",
"operation": "update",
"entityId": "risk_auth_001",
"suggestedData": {
"status": "MITIGATED",
"severity": "MEDIUM"
}
}
}
Example: Delete Control
{
"tool": "suggest_change",
"arguments": {
"entityType": "control",
"operation": "delete",
"entityId": "ctrl_mfa_deprecated"
}
}
Return Value
{
success: boolean;
suggestionId: string;
message: string;
}
Example Response:
{
"success": true,
"suggestionId": "sugg_abc123",
"message": "Suggestion created successfully. User must approve before changes are applied."
}
2. query_data
Execute GraphQL queries to retrieve data.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Yes | GraphQL query string (must be valid GraphQL syntax) |
variables | object | No | GraphQL query variables (for parameterized queries) |
Common Query Patterns
Pattern 1: Get Entities with Filters
query GetAudits($status: String) {
audits(status: $status) {
id
title
status
dueDate
owner {
name
email
}
}
}
Usage:
{
"tool": "query_data",
"arguments": {
"query": "query GetAudits($status: String) { audits(status: $status) { id title status dueDate } }",
"variables": {
"status": "IN_PROGRESS"
}
}
}
Pattern 2: Get CustomList Values (CRITICAL)
IMPORTANT: Always query CustomList values before using status/severity/type fields in suggestions.
query GetAuditStatuses {
customLists(category: "AUDIT_STATUS") {
id
value
label
sortOrder
}
}
Available CustomList categories:
AUDIT_STATUS- Audit statuses (e.g., PLANNING, IN_PROGRESS, COMPLETED)AUDIT_TYPE- Audit types (e.g., COMPLIANCE, INTERNAL, EXTERNAL)ISSUE_SEVERITY- Issue severities (e.g., LOW, MEDIUM, HIGH, CRITICAL)ISSUE_STATUS- Issue statuses (e.g., OPEN, IN_PROGRESS, RESOLVED, CLOSED)RISK_SEVERITY- Risk severities (e.g., LOW, MEDIUM, HIGH, CRITICAL)RISK_LIKELIHOOD- Risk likelihoods (e.g., RARE, UNLIKELY, POSSIBLE, LIKELY, CERTAIN)RISK_STATUS- Risk statuses (e.g., IDENTIFIED, ASSESSED, MITIGATED, ACCEPTED)CONTROL_TYPE- Control types (e.g., PREVENTIVE, DETECTIVE, CORRECTIVE)CONTROL_FREQUENCY- Control frequencies (e.g., CONTINUOUS, DAILY, WEEKLY, MONTHLY)CONTROL_STATUS- Control statuses (e.g., PLANNED, IMPLEMENTED, OPERATING, INEFFECTIVE)WORKFLOW_STATUS- Workflow statuses (e.g., DRAFT, ACTIVE, COMPLETED, ARCHIVED)
Usage:
{
"tool": "query_data",
"arguments": {
"query": "query GetStatuses { customLists(category: \"AUDIT_STATUS\") { value label } }"
}
}
Response:
{
"data": {
"customLists": [
{ "value": "PLANNING", "label": "Planning" },
{ "value": "IN_PROGRESS", "label": "In Progress" },
{ "value": "COMPLETED", "label": "Completed" }
]
}
}
Pattern 3: Search Entities
query SearchAudits($searchTerm: String!) {
audits(search: $searchTerm) {
id
title
description
status
}
}
Usage:
{
"tool": "query_data",
"arguments": {
"query": "query Search($searchTerm: String!) { audits(search: $searchTerm) { id title description } }",
"variables": {
"searchTerm": "SOC2"
}
}
}
Pattern 4: Get Entity Details
query GetAuditDetails($id: ID!) {
audit(id: $id) {
id
title
description
status
type
startDate
endDate
budgetHours
owner {
id
name
email
}
workflows {
id
name
status
}
documents {
id
title
fileName
}
}
}
Pattern 5: Get Pending Suggestions
query GetPendingSuggestions {
mySuggestions(status: "pending") {
id
entityType
entityId
entityName
operation
suggestedData
agentType
agentName
agentPrompt
createdAt
}
}
Pattern 6: Get Artifact with Workflow Context
Use artifactWithContext to get an artifact along with all its upstream workflow dependencies in one optimized query. This is essential when helping users complete workflow artifacts.
query GetArtifactWithContext($id: ID!) {
artifactWithContext(id: $id) {
# Target artifact
id
name
description
instructions
status
dueDate
# Linked document
platform
shareableLink
fileName
mimeType
# Workflow context
workflowId
workflowName
workflowDescription
diagramNodeId
# Upstream dependencies (APPROVAL-GATED)
upstreamArtifacts {
id
name
description
instructions
status
dueDate
# Approval status
isApproved # true if allApprovalsMetAt is set
approvedCount # Current approval count
requiredApprovals # Required approvals
archivalStatus # 'archived' | 'invalidated' | 'pending' | null
accessWarning # Warning message if blocked
# Document access (only if approved AND archived)
platform
shareableLink # null if not approved
gcpStorageUrl # null if not approved or archivalStatus != 'archived'
fileName
diagramNodeId
}
}
}
Typical Workflow:
- Call
get_current_context()→ get the current artifact ID - Call
query_datawithartifactWithContext→ get artifact + all upstream context - AI now knows: what this artifact is, what it depends on, what's already done
- Make smart suggestions referencing upstream artifacts
Note: Upstream artifact document URLs (shareableLink, gcpStorageUrl) are only returned if the artifact is approved and archived.
Pattern 7: Get Entity with All Relationships
Use entityWithRelationships to get any entity along with all its relationships and full related entity data. This is essential for Risk-Control matrices, audit trails, gap analysis, and issue root cause analysis.
query GetEntityWithRelationships($entityType: String!, $entityId: String!) {
entityWithRelationships(
entityType: $entityType
entityId: $entityId
relationshipTypes: ["mitigates", "identifies"] # Optional filter
direction: "both" # 'both' | 'outgoing' | 'incoming'
) {
# Source entity
entity {
id
type # 'risk', 'control', 'audit', 'issue', etc.
name
description
status
data # Full entity data as JSON
}
# All relationships with related entity details
relationships {
id
relationshipType # "mitigates", "identifies", "tests", etc.
direction # "directional" | "bidirectional"
metadata # JSON: { effectiveness: 0.85, notes: "..." }
isOutgoing # true if this entity is source, false if target
# Related entity full data
relatedEntity {
id
type
name
description
status
data # Full entity data
}
createdAt
}
# Summary statistics
stats {
totalRelationships
byType {
relationshipType
count
}
byDirection {
outgoing
incoming
}
}
}
}
Common Use Cases:
| Use Case | Query Example |
|---|---|
| Risk-Control Matrix | entityWithRelationships(entityType: "risk", entityId: "...", relationshipTypes: ["mitigates"]) |
| Audit Trail | entityWithRelationships(entityType: "audit", entityId: "...") |
| Gap Analysis | Query all risks, check stats.totalRelationships for each |
| Issue Root Cause | entityWithRelationships(entityType: "issue", entityId: "...", relationshipTypes: ["causes"]) |
Example Usage:
{
"tool": "query_data",
"arguments": {
"query": "query { entityWithRelationships(entityType: \"risk\", entityId: \"risk_auth_bypass\") { entity { id name } relationships { relationshipType relatedEntity { id type name } } stats { totalRelationships } } }"
}
}
Pattern 8: Get Comprehensive Entity Details
Use entityDetails to get complete entity information with all related entities. This query only supports audit, issue, risk, and control entity types (not workflows, artifacts, or dashboards).
query GetEntityDetails($entityType: String!, $entityId: String!) {
entityDetails(
entityType: $entityType
entityId: $entityId
includeRelationships: true # Optional, defaults to true
relationshipTypes: ["MITIGATES"] # Optional filter
relatedEntityTypes: ["control"] # Optional filter
) {
entity {
id
type
name
description
status
createdAt
updatedAt
ownerId
data # Full entity data as JSON (all type-specific fields)
}
relatedEntities {
relationshipId
relationshipType
isOutgoing
relationshipMetadata
createdAt
entity {
id
type
name
description
status
data # Full related entity data
}
}
stats {
totalRelationships
byType # [{ relationshipType: "MITIGATES", count: 5 }]
byEntityType # [{ entityType: "control", count: 5 }]
outgoingCount
incomingCount
}
}
}
Differences from entityWithRelationships:
| Feature | entityWithRelationships | entityDetails |
|---|---|---|
| Supported entity types | All (audit, issue, risk, control, workflow, artifact, dashboard) | Only audit, issue, risk, control |
| Entity data format | data field with full JSON | data field with full JSON |
| Relationship filtering | By type and direction | By type and related entity type |
| Include relationships | Always included | Optional via includeRelationships |
Common Use Cases:
- Complete Risk-Control Matrix export
- Full audit context for compliance reporting
- Issue analysis with all related entities
- Gap analysis with detailed entity data
Example Usage:
{
"tool": "query_data",
"arguments": {
"query": "query { entityDetails(entityType: \"risk\", entityId: \"risk_data_breach\", includeRelationships: true, relatedEntityTypes: [\"control\"]) { entity { id name data } relatedEntities { relationshipType entity { id name } } stats { totalRelationships } } }"
}
}
Return Value
Returns the GraphQL query result as JSON.
Example Response:
{
"data": {
"audits": [
{
"id": "audit_123",
"title": "Q1 2025 SOC2 Review",
"status": "IN_PROGRESS",
"dueDate": "2025-02-15"
}
]
}
}
Error Handling
If the query fails, you'll receive an error:
{
"errors": [
{
"message": "Field 'invalidField' doesn't exist on type 'Audit'",
"locations": [{ "line": 2, "column": 5 }]
}
]
}
3. get_current_context
Get the user's current page context for context-aware assistance.
Parameters
None.
Return Value
{
pageUrl: string; // Current page URL
pageType: string; // Page type identifier
entityId: string | null; // ID of entity being viewed (if applicable)
entityType: string | null; // Type of entity being viewed (if applicable)
pageData: object | null; // Additional page context
}
Page Types
| Page Type | Description | Entity Type | Entity ID |
|---|---|---|---|
audit-list | Audits list page | null | null |
audit-detail | Audit detail page | audit | audit_123 |
issue-list | Issues list page | null | null |
issue-detail | Issue detail page | issue | issue_456 |
risk-list | Risks list page | null | null |
risk-detail | Risk detail page | risk | risk_789 |
control-list | Controls list page | null | null |
control-detail | Control detail page | control | control_012 |
workflow-detail | Workflow detail page | workflow | workflow_345 |
dashboard-detail | Dashboard detail page | dashboard | dash_678 |
home | Home page | null | null |
Example Usage
{
"tool": "get_current_context",
"arguments": {}
}
Example Response
{
"pageUrl": "/audits/audit_soc2_q1",
"pageType": "audit-detail",
"entityId": "audit_soc2_q1",
"entityType": "audit",
"pageData": {
"title": "Q1 2025 SOC2 Review",
"status": "IN_PROGRESS",
"dueDate": "2025-02-15"
}
}
Context-Aware Workflow
Use context to provide relevant suggestions:
// 1. Get context
const context = await get_current_context();
// 2. Check what page user is viewing
if (context.pageType === "audit-detail" && context.entityId) {
// User is viewing an audit - suggest audit-related actions
await suggest_change({
entityType: "audit",
operation: "update",
entityId: context.entityId,
suggestedData: { status: "IN_PROGRESS" }
});
} else if (context.pageType === "audit-list") {
// User is viewing audit list - suggest creating a new audit
await suggest_change({
entityType: "audit",
operation: "create",
suggestedData: {
title: "New Compliance Audit",
status: "PLANNING"
}
});
}
4. help
Get dual-path workflow guidance (manual UI steps + automated agent steps).
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
topic | string | Yes | Help topic (see Available Topics) |
audience | string | No | user (manual steps), agent (automated), or both (default) |
Available Topics
| Topic | Description |
|---|---|
overview | AuditSwarm platform overview |
add-document | Adding documents to knowledge base |
link-external-document | Linking OneDrive/Google Drive docs |
create-workflow | Creating workflows (template-based) |
create-dashboard | Creating custom dashboards |
create-audit | Starting new audits |
search-documents | Searching documents |
approve-suggestions | Understanding the approval workflow |
ai-agents-intro | How AI agents work with AuditSwarm |
troubleshooting | Common issues and solutions |
Return Value
{
topic: string;
userSteps?: string[]; // Manual UI steps (if audience includes 'user')
agentSteps?: string[]; // Automated agent steps (if audience includes 'agent')
tips?: string[]; // Additional tips
relatedTopics?: string[]; // Related help topics
}
Example Usage
{
"tool": "help",
"arguments": {
"topic": "link-external-document",
"audience": "both"
}
}
Example Response
{
"topic": "link-external-document",
"userSteps": [
"Navigate to the workflow/audit/artifact page",
"Click 'Link Document' button",
"Paste the OneDrive or Google Drive URL",
"Fill in metadata (optional)",
"Click 'Save'"
],
"agentSteps": [
"Call get_current_context() to identify the entity",
"Call suggest_change with entityType='artifact' and operation='create'",
"Include shareableLink in suggestedData",
"User approves the suggestion"
],
"tips": [
"Documents remain in their original location (OneDrive/Google Drive)",
"Only metadata is stored in AuditSwarm",
"Ensure the link is publicly accessible or shared with users"
],
"relatedTopics": [
"add-document",
"approve-suggestions"
]
}
Using Help for Educational Experiences
The help tool enables dual-path workflows where users can:
- Learn the UI - See manual steps to understand the platform
- Save time - Let the AI agent automate the workflow
Example agent behavior:
User: "How do I link a document?"
Agent calls: help({ topic: 'link-external-document', audience: 'both' })
Agent responds:
"To link an external document manually:
1. Navigate to the workflow page
2. Click 'Link Document'
3. Paste the URL
...
Or I can do this for you! Just provide the document URL,
and I'll create a link suggestion for your approval.
Would you like to do it manually or have me help?"
5. upload_document_for_archival
Upload documents for compliance archival and create artifact approval suggestion.
Overview
This tool combines two operations into ONE suggestion:
- Upload document to GCP Storage for 7-year retention
- Create artifact approval suggestion
When approved, both actions complete atomically (all-or-nothing).
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
artifactId | string | Yes | Artifact ID to upload document for |
fileBuffer | string | Yes | Base64-encoded file content |
fileName | string | Yes | Original filename (e.g., "Risk_Assessment_v2.pdf") |
mimeType | string | No | MIME type (e.g., "application/pdf") |
fileHash | string | Yes | SHA-256 hash for verification |
agentMetadata | object | No | Agent info for audit trail |
Agent Metadata Object
| Field | Type | Required | Description |
|---|---|---|---|
agentName | string | No | AI agent name (e.g., "Claude Desktop") |
agentPlatform | string | No | Platform (e.g., "claude", "chatgpt") |
agentModel | string | No | Model name (e.g., "claude-3-opus") |
downloadedFrom | string | No | Source URL (e.g., OneDrive URL) |
Workflow
1. AI downloads document from artifact.shareableLink using platform connector
↓
2. AI calculates SHA-256 hash for integrity verification
↓
3. AI encodes file to base64 and calls this tool
↓
4. System uploads to GCP Storage and creates DocumentVersion (not current)
↓
5. System creates ONE suggestion combining archival + approval
↓
6. User sees suggestion card with document preview
↓
7. User approves suggestion
↓
8. System atomically:
- Marks DocumentVersion as current
- Creates ArtifactApproval record
- Updates Artifact link to GCP Storage URL
- Locks artifact if all approvals met
Example Usage
// User: "Approve artifact abc123 and archive the document"
// Step 1: Get artifact details
const artifact = await query_data({
query: `query GetArtifact($id: ID!) {
artifact(id: $id) {
id
name
shareableLink
platform
}
}`,
variables: { id: "abc123" }
});
// Step 2: Download file using platform connector
// (Microsoft Graph API for OneDrive, Google Drive API, etc.)
const response = await fetch(artifact.data.artifact.shareableLink, {
headers: { Authorization: `Bearer ${oneDriveToken}` }
});
const fileBuffer = await response.arrayBuffer();
// Step 3: Calculate SHA-256 hash
const crypto = require('crypto');
const fileHash = crypto
.createHash('sha256')
.update(Buffer.from(fileBuffer))
.digest('hex');
// Step 4: Encode to base64
const fileBase64 = Buffer.from(fileBuffer).toString('base64');
// Step 5: Upload document
const result = await upload_document_for_archival({
artifactId: "abc123",
fileBuffer: fileBase64,
fileName: "Risk_Assessment_2024.pdf",
mimeType: "application/pdf",
fileHash: fileHash,
agentMetadata: {
agentName: "Claude Desktop",
agentPlatform: "claude",
agentModel: "claude-3-opus",
downloadedFrom: artifact.data.artifact.shareableLink
}
});
// Step 6: Notify user
console.log(`Document uploaded! Suggestion ID: ${result.suggestionId}`);
console.log("Please approve the suggestion to finalize archival and approval.");
Example Request
{
"tool": "upload_document_for_archival",
"arguments": {
"artifactId": "artifact_abc123",
"fileBuffer": "JVBERi0xLjQKJeLjz9MKM...",
"fileName": "Risk_Assessment_2024.pdf",
"mimeType": "application/pdf",
"fileHash": "a1b2c3d4e5f6...",
"agentMetadata": {
"agentName": "Claude Desktop",
"agentPlatform": "claude",
"agentModel": "claude-3-opus",
"downloadedFrom": "https://onedrive.live.com/..."
}
}
}
Return Value
{
success: boolean;
message: string;
suggestionId: string;
documentVersionId: string;
gcpStorageUrl: string; // Temporary preview URL (7 days)
}
Example Response
{
"success": true,
"message": "Document uploaded and approval suggestion created. User will see ONE suggestion card combining both the archival and approval.",
"suggestionId": "sugg_xyz789",
"documentVersionId": "docver_123",
"gcpStorageUrl": "https://storage.googleapis.com/..."
}
Security Features
- Hash Verification: SHA-256 hash is verified server-side to ensure file integrity
- Staging Upload: Document uploaded to GCP but marked as
isCurrent: falseuntil approved - Audit Trail: Agent metadata logged for compliance tracking
- Atomic Approval: Both archival and approval happen in a single database transaction
- Cleanup on Rejection: If suggestion is rejected, the GCP file is deleted
Error Handling
File too large:
{
"success": false,
"error": "File too large. Maximum size is 100MB, got 150.5MB"
}
Hash mismatch:
{
"success": false,
"error": "File hash mismatch - file integrity check failed"
}
Artifact not found:
{
"success": false,
"error": "Artifact not found"
}
Common Platforms & Connectors
Microsoft OneDrive / SharePoint
// Download from OneDrive
const response = await fetch(shareableLink, {
headers: {
'Authorization': `Bearer ${msGraphToken}`
}
});
const fileBuffer = await response.arrayBuffer();
Google Drive
// Download from Google Drive
const { google } = require('googleapis');
const drive = google.drive({ version: 'v3', auth: oAuth2Client });
const response = await drive.files.get(
{ fileId: fileId, alt: 'media' },
{ responseType: 'arraybuffer' }
);
const fileBuffer = response.data;
Best Practices
- Always provide fileHash - Required for compliance and integrity verification
- Include agent metadata - Critical for audit trails
- Check file size first - Maximum 100MB
- Use streaming for large files - Download in chunks if needed
- Handle errors gracefully - Inform user if download/upload fails
- Provide clear messaging - Tell user what happens when they approve
Difference from suggest_change
| Feature | suggest_change | upload_document_for_archival |
|---|---|---|
| File upload | No | Yes (to GCP Storage) |
| Immediate action | No | Yes (file uploaded) |
| Requires approval | Yes | Yes (for finalizing) |
| Creates suggestion | Yes | Yes |
| Entity types | All entities | Only artifact_approval |
| Cleanup on reject | N/A | Yes (deletes GCP file) |
AI Suggestions - Complete Field Reference
When creating suggestions via suggest_change, the suggestion is stored in the database with the following fields. Understanding these fields helps you create better suggestions and know what will appear in the UI.
Required Fields (AI must provide)
| Field | Type | Provided By | Description |
|---|---|---|---|
entityType | string | Tool parameter | Type of entity (e.g., 'audit', 'issue', 'artifact_approval') |
operation | string | Tool parameter | Operation type ('create', 'update', 'delete', 'approve_with_archival') |
suggestedData | JSON | Tool parameter | The actual changes being suggested |
agentType | string | Tool parameter | AI agent type ('claude', 'chatgpt', 'copilot', 'custom') |
Optional Fields (AI can provide)
| Field | Type | Provided By | Description | UI Visibility |
|---|---|---|---|---|
entityId | string | Tool parameter | ID of entity (required for update/delete, null for create) | - |
originalData | JSON | Tool parameter | Original values for showing diffs | Expanded view |
contextData | JSON | Tool parameter | Additional context data | - |
reasoning | string | Tool parameter | Why the AI made this suggestion | - |
agentId | string | agentMetadata.id | Unique identifier for the agent instance | - |
agentName | string | agentMetadata.name | User-friendly agent name (e.g., "Document Archival Agent") | - |
agentPrompt | string | Set separately | This is the description! Human-readable explanation | List item main content |
System-Generated Fields (Auto-populated)
| Field | Type | Description | UI Visibility |
|---|---|---|---|
id | string | Unique suggestion ID | - |
userId | string | User who owns this suggestion | - |
status | string | 'pending', 'approved', or 'rejected' | Status icon |
createdAt | DateTime | When suggestion was created | Bottom row timestamp |
processedAt | DateTime | When suggestion was approved/rejected | - |
processedBy | string | User who processed the suggestion | - |
contextPageType | string | Type of page user was viewing | - |
contextPageUrl | string | URL of page user was viewing | - |
entityName | string | Computed field - Extracted from suggestedData | Bottom row |
What Displays in the Suggestions List UI
When users view suggestions, here's what appears on each list item:
Top Row (Badges):
- Operation badge (Create/Update/Delete) - from
operationfield - Entity type badge (audit, issue, etc.) - from
entityTypefield - Agent badge (Claude, ChatGPT, Copilot) - from
agentTypefield - Status icon (pending/approved/rejected) - from
statusfield
Main Content:
agentPrompt(italic, gray text) - The human-readable description- Example: "Document has been downloaded from SharePoint and is ready for approval..."
- This is what users see to understand what the suggestion does
- Best practice: Provide a clear, concise description of the action
Special Content (for artifact_approval type only):
- Workflow name: Extracted from
suggestedData.workflowName - Artifact name: Extracted from
suggestedData.artifactName - Document filename: Extracted from
suggestedData.documentVersion.fileName - Preview link: From
suggestedData.documentVersion.gcpStorageUrl
Bottom Row:
- Timestamp (e.g., "2 days ago") - from
createdAtfield - Entity name - Extracted from
suggestedData.title,suggestedData.name, orsuggestedData.artifactName
Best Practices for agentPrompt
The agentPrompt field is what users see to understand your suggestion. Write clear, user-friendly descriptions:
✅ Good Examples:
"Update audit status to reflect current progress"
"Archive compliance document for 7-year retention"
"Link risk assessment to SOC2 control framework"
"Mark issue as resolved after verification"
❌ Bad Examples:
"Update entity" (too vague)
"Change status field" (technical, not user-friendly)
"Mutation executed" (not helpful)
Format:
- Action verb + what + why (optional)
- Keep it under 100 characters
- Use plain language, not technical jargon
- Explain the outcome, not the mechanics
Example: Complete Suggestion
Here's a complete example showing all fields and how they appear in the UI:
{
"tool": "suggest_change",
"arguments": {
"entityType": "audit",
"operation": "update",
"entityId": "audit_soc2_q1",
"suggestedData": {
"title": "Q1 2025 SOC2 Review",
"status": "IN_PROGRESS"
},
"agentMetadata": {
"name": "Compliance Assistant",
"platform": "claude",
"model": "claude-3-opus",
"specialization": "SOC2 compliance"
}
}
}
Additionally set via GraphQL mutation:
{
"agentPrompt": "Update audit status to in-progress after kickoff meeting"
}
How this appears in the UI:
┌─────────────────────────────────────────────────────┐
│ 🐝 [Update] [audit] [Claude] ⏰ │ ← Top Row
│ │
│ "Update audit status to in-progress after │ ← agentPrompt
│ kickoff meeting" │
│ │
│ 2 hours ago • Q1 2025 SOC2 Review │ ← Bottom Row
└─────────────────────────────────────────────────────┘
Common Patterns & Workflows
Pattern 1: Context-Aware Suggestions
Always use context to make relevant suggestions:
// 1. Get user's current page
const context = await get_current_context();
// 2. Use context to determine appropriate action
if (context.entityType === "audit" && context.entityId) {
await suggest_change({
entityType: "audit",
operation: "update",
entityId: context.entityId,
suggestedData: { status: "IN_PROGRESS" }
});
}
Pattern 2: Dynamic Enum Values (CRITICAL)
Always query CustomList before using status/severity/type fields:
// 1. Query valid values first
const validStatuses = await query_data({
query: 'query { customLists(category: "AUDIT_STATUS") { value } }'
});
// 2. Use actual value from CustomList
await suggest_change({
entityType: "audit",
operation: "update",
entityId: "audit_123",
suggestedData: {
status: validStatuses.data.customLists[0].value // Use real value, not hardcoded
}
});
Pattern 3: Search Before Suggest
Prevent duplicate entities by searching first:
// 1. Search for existing entity
const existing = await query_data({
query: 'query Search($term: String!) { risks(search: $term) { id title } }',
variables: { term: "Data Breach" }
});
// 2. Update if exists, create if not
if (existing.data.risks.length > 0) {
await suggest_change({
operation: "update",
entityId: existing.data.risks[0].id,
suggestedData: { severity: "HIGH" }
});
} else {
await suggest_change({
operation: "create",
suggestedData: {
name: "Data Breach Risk",
severity: "HIGH"
}
});
}
Pattern 4: Dual-Path User Experience
Use help to educate users while automating:
// 1. Provide manual steps
const helpResponse = await help({
topic: "link-external-document",
audience: "both"
});
// 2. Present options to user
console.log("Manual steps:", helpResponse.userSteps);
console.log("Or I can automate it for you!");
// 3. If user agrees, automate
await suggest_change({
entityType: "artifact",
operation: "create",
suggestedData: {
name: "SOC2 Policy Document",
shareableLink: "https://onedrive.com/..."
}
});
Pattern 5: Error Handling
Always handle errors gracefully:
try {
const result = await suggest_change({
entityType: "audit",
operation: "create",
suggestedData: { title: "New Audit" }
});
console.log("Suggestion created:", result.suggestionId);
} catch (error) {
if (error.message.includes("CustomList")) {
// User needs to query valid values first
console.log("Please query valid status values using query_data");
} else {
console.error("Failed to create suggestion:", error.message);
}
}
Security & Limitations
✅ What Agents CAN Do:
- Create suggestions for any entity type
- Query all data user has access to
- Get user's current context
- Access workflow guidance
- Read CustomList values
- Search entities
❌ What Agents CANNOT Do:
- Directly modify production data (suggestions only)
- Access data from other users (enforced by OAuth)
- Bypass approval workflow
- Execute arbitrary SQL
- Access file system
- Delete other users' data
Approval Required:
All suggest_change operations require explicit user approval before being applied to production data. This ensures:
- Users remain in control
- Changes are reviewed before application
- Audit trail is maintained
- AI cannot make mistakes that affect production
Rate Limiting:
- 100 requests per minute per user
- 1000 requests per hour per user
- Exceeded limits return HTTP 429 (Too Many Requests)