Skip to main content
Glama

inkog_verify_governance

Validate that AGENTS.md governance declarations match actual code behavior. Detects mismatches like declared read-only accessing data or missing approval gates for required human approval.

Instructions

Validate that AGENTS.md declarations match actual code behavior. Detects governance mismatches like 'read-only declared but code writes data' or 'human approval required but no approval gates in code'. Essential for EU AI Act Article 14 compliance. Use this whenever an AI agent project has an AGENTS.md file, or to verify governance compliance before deployment.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYesPath to directory containing AGENTS.md and agent code

Implementation Reference

  • The main handler function 'governanceHandler' that executes the inkog_verify_governance tool logic. Validates AGENTS.md declarations against actual code behavior by scanning files, calling the Inkog API to verify governance, and formatting a comprehensive report.
    async function governanceHandler(rawArgs: Record<string, unknown>): Promise<ToolResult> {
      // Validate arguments
      const parseResult = GovernanceArgsSchema.safeParse(rawArgs);
      if (!parseResult.success) {
        return {
          content: [
            {
              type: 'text',
              text: `Invalid arguments: ${parseResult.error.message}`,
            },
          ],
          isError: true,
        };
      }
    
      const args: GovernanceArgs = parseResult.data;
    
      try {
        // Check for AGENTS.md
        const agentsMdPath = findAgentsMd(args.path);
    
        // Read files from path
        const readResult = readDirectory(args.path);
    
        if (readResult.files.length === 0) {
          return {
            content: [
              {
                type: 'text',
                text: `No files found in: ${args.path}`,
              },
            ],
            isError: true,
          };
        }
    
        // Get relative paths for cleaner output
        const files = getRelativePaths(readResult.files, args.path);
    
        // Call Inkog API - first scan, then verify governance
        const client = getClient();
    
        // Step 1: Run a scan to get a scan_id
        const scanResponse = await client.scan(files, { policy: 'governance' });
        if (!scanResponse.success || !scanResponse.scan_id) {
          return {
            content: [
              {
                type: 'text',
                text: 'Scan failed: Unable to analyze files',
              },
            ],
            isError: true,
          };
        }
    
        // Step 2: Use scan_id to verify governance
        const response = await client.verifyGovernance({ scanId: scanResponse.scan_id });
    
        // Build output
        let output = '╔══════════════════════════════════════════════════════╗\n';
        output += '║        🏛️  AGENTS.md Governance Verification          ║\n';
        output += '╚══════════════════════════════════════════════════════╝\n\n';
    
        // AGENTS.md status
        const hasAgentsMd = response.hasAgentsMd ?? (agentsMdPath !== null);
        if (hasAgentsMd) {
          output += `✅ AGENTS.md found: ${agentsMdPath ?? 'AGENTS.md'}\n\n`;
        } else {
          output += '⚠️  No AGENTS.md file found\n\n';
          output +=
            'AGENTS.md is a governance declaration file that describes what your agent\n';
          output += 'can and cannot do. It helps ensure your agent behaves as documented.\n\n';
          output += 'To create one, add an AGENTS.md file to your project root with:\n';
          output += '- Capabilities: What the agent can do\n';
          output += '- Limitations: What the agent cannot do\n';
          output += '- Tools: What tools the agent has access to\n';
          output += '- Security: Required security controls\n\n';
          output +=
            'Learn more: https://docs.inkog.io/governance/agents-md\n\n';
        }
    
        // Overall status and score
        output += `📊 Status: ${formatOverallStatus(response.overall_status)}\n`;
        output += `📈 Governance Score: ${formatScore(response.score)}\n\n`;
    
        // Summary if available
        if (response.summary) {
          output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n';
          output += '📊 SUMMARY\n\n';
          output += `   Total declarations: ${response.summary.total_declarations}\n`;
          output += `   ✅ Valid: ${response.summary.valid_declarations}\n`;
          output += `   ❌ Violated: ${response.summary.violated_constraints}\n`;
          output += `   ⚪ Unverified: ${response.summary.unverified_items}\n`;
          output += `   📁 Files analyzed: ${response.summary.files_analyzed}\n\n`;
        }
    
        // Declared capabilities
        const declaredCaps = response.declared_capabilities ?? [];
        if (declaredCaps.length > 0) {
          output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n';
          output += '📜 DECLARED CAPABILITIES\n\n';
    
          // Group by status
          const valid = declaredCaps.filter((c) => c.status === 'valid');
          const violated = declaredCaps.filter((c) => c.status === 'violated');
          const unverified = declaredCaps.filter((c) => c.status === 'unverified');
    
          if (violated.length > 0) {
            output += '❌ VIOLATED:\n\n';
            for (const cap of violated) {
              output += formatCapability(cap);
            }
            output += '\n';
          }
    
          if (unverified.length > 0) {
            output += '⚪ UNVERIFIED:\n\n';
            for (const cap of unverified) {
              output += formatCapability(cap);
            }
            output += '\n';
          }
    
          if (valid.length > 0) {
            output += '✅ VALID:\n\n';
            for (const cap of valid) {
              output += `   ${cap.name}`;
              if (cap.constraint_type) {
                output += ` [${cap.constraint_type}]`;
              }
              output += '\n';
            }
            output += '\n';
          }
        }
    
        // Mismatches
        const mismatches = response.mismatches ?? [];
        if (mismatches.length > 0) {
          output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n';
          output += `⚠️  GOVERNANCE MISMATCHES (${mismatches.length})\n\n`;
          output += 'The following code behaviors do not match AGENTS.md declarations:\n\n';
    
          for (const mismatch of mismatches) {
            output += formatMismatch(mismatch) + '\n';
          }
        } else if (hasAgentsMd) {
          output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n';
          output += '✅ No governance mismatches detected!\n\n';
          output += 'Your agent code aligns with its AGENTS.md declarations.\n\n';
        }
    
        // Recommendations
        const recommendations = response.recommendations ?? [];
        if (recommendations.length > 0) {
          output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n';
          output += '💡 RECOMMENDATIONS\n\n';
          for (let i = 0; i < recommendations.length; i++) {
            output += `${i + 1}. ${recommendations[i]}\n`;
          }
        }
    
        // Footer
        output += '\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
        output += 'AGENTS.md verification powered by Inkog AI Security Platform\n';
        output += 'Learn more: https://inkog.io/governance\n';
    
        return {
          content: [
            {
              type: 'text',
              text: output,
            },
          ],
        };
      } catch (error) {
        if (error instanceof InkogAuthError) {
          return {
            content: [
              {
                type: 'text',
                text: '🔐 API Key Required\n\nTo use Inkog, you need an API key.\n\n1. Sign up for free at https://app.inkog.io\n2. Set your API key: export INKOG_API_KEY=sk_live_...\n3. Try again!',
              },
            ],
            isError: true,
          };
        }
    
        if (error instanceof InkogRateLimitError) {
          return {
            content: [
              {
                type: 'text',
                text: `⏱️ Rate Limited\n\nToo many requests. Please retry after ${error.retryAfter} seconds.`,
              },
            ],
            isError: true,
          };
        }
    
        if (error instanceof InkogNetworkError) {
          return {
            content: [
              {
                type: 'text',
                text: `Network error: ${error.message}\n\nPlease check your internet connection and try again.`,
              },
            ],
            isError: true,
          };
        }
    
        if (error instanceof InkogApiError) {
          return {
            content: [
              {
                type: 'text',
                text: `API error: ${error.message}${error.details ? `\n\nDetails: ${JSON.stringify(error.details)}` : ''}`,
              },
            ],
            isError: true,
          };
        }
    
        const message = error instanceof Error ? error.message : 'Unknown error occurred';
        return {
          content: [
            {
              type: 'text',
              text: `Error: ${message}`,
            },
          ],
          isError: true,
        };
      }
    }
  • Zod schema 'GovernanceArgsSchema' defining the input arguments for the tool (path: string to directory containing AGENTS.md and agent code).
    const GovernanceArgsSchema = z.object({
      path: z.string().describe('Path to directory containing AGENTS.md and agent code'),
    });
    
    type GovernanceArgs = z.infer<typeof GovernanceArgsSchema>;
  • The exported 'governanceTool' ToolDefinition object that registers the tool with name 'inkog_verify_governance', its description, inputSchema, and links to the governanceHandler.
    export const governanceTool: ToolDefinition = {
      tool: {
        name: 'inkog_verify_governance',
        description:
          "Validate that AGENTS.md declarations match actual code behavior. Detects governance mismatches like 'read-only declared but code writes data' or 'human approval required but no approval gates in code'. Essential for EU AI Act Article 14 compliance. Use this whenever an AI agent project has an AGENTS.md file, or to verify governance compliance before deployment.",
        inputSchema: {
          type: 'object',
          properties: {
            path: {
              type: 'string',
              description: 'Path to directory containing AGENTS.md and agent code',
            },
          },
          required: ['path'],
        },
      },
      handler: governanceHandler,
    };
  • Import and registration of the governanceTool in the central tool registry (src/tools/index.ts), making it available to the MCP server.
    import { governanceTool } from './governance.js';
    import { complianceTool } from './compliance.js';
    import { explainTool } from './explain.js';
    import { auditMcpTool } from './audit-mcp.js';
    import { mlbomTool } from './mlbom.js';
    import { auditA2aTool } from './audit-a2a.js';
    import { skillScanTool } from './skill-scan.js';
    import { mcpScanTool } from './mcp-scan.js';
    
    // Register all tools
    registerTool(scanTool);
    registerTool(deepScanTool);
    registerTool(governanceTool);
  • Helper functions (formatSeverityIcon, formatMismatch, formatCapability, formatScore, formatOverallStatus) used for formatting governance verification output.
    function formatSeverityIcon(severity: string): string {
      const upper = severity.toUpperCase();
      switch (upper) {
        case 'CRITICAL':
          return '🔴';
        case 'HIGH':
          return '🟠';
        case 'MEDIUM':
          return '🟡';
        case 'LOW':
          return '🟢';
        default:
          return '⚪';
      }
    }
    
    function formatMismatch(mismatch: GovernanceMismatch): string {
      const icon = formatSeverityIcon(mismatch.severity);
    
      let output = `${icon} GOVERNANCE MISMATCH [${mismatch.severity.toUpperCase()}]\n`;
      output += `   📍 ${mismatch.file}:${mismatch.line}\n`;
      output += `   🎯 Capability: ${mismatch.capability}\n`;
      output += `   📜 Expected: "${mismatch.expected}"\n`;
      output += `   ⚠️  Actual: "${mismatch.actual}"\n`;
    
      if (mismatch.evidence) {
        output += `   📝 Evidence: ${mismatch.evidence}\n`;
      }
    
      return output;
    }
    
    function formatCapability(cap: DeclaredCapability): string {
      const statusIcon = cap.status === 'valid' ? '✅' :
                         cap.status === 'violated' ? '❌' : '⚪';
    
      let output = `${statusIcon} ${cap.name}`;
      if (cap.constraint_type) {
        output += ` [${cap.constraint_type}]`;
      }
      output += '\n';
    
      if (cap.description) {
        output += `      ${cap.description}\n`;
      }
    
      if (cap.line) {
        output += `      Line: ${cap.line}\n`;
      }
    
      return output;
    }
    
    function formatScore(score: number): string {
      if (score >= 90) {
        return `✅ ${score}/100 (Excellent)`;
      } else if (score >= 70) {
        return `🟢 ${score}/100 (Good)`;
      } else if (score >= 50) {
        return `🟡 ${score}/100 (Fair)`;
      } else if (score >= 30) {
        return `🟠 ${score}/100 (Poor)`;
      } else {
        return `🔴 ${score}/100 (Critical)`;
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It does not explicitly state whether the tool is read-only, modifies any files, or requires network access. The detection examples imply it is a static analysis tool, but this is not confirmed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with four sentences covering purpose, examples, compliance context, and usage guidance. No unnecessary words, but could be slightly tighter by merging sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description fails to explain what the tool returns (e.g., list of mismatches, pass/fail, report). For a verification tool, this is a significant omission, making it incomplete for an agent to fully understand behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with the path parameter described adequately. The description reinforces the purpose of the path but adds no new parameter details beyond what the schema provides, giving a baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool validates AGENTS.md declarations against code behavior with specific examples of governance mismatches. It distinguishes itself from sibling scanning/audit tools by focusing specifically on governance compliance.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance: use when an AGENTS.md file exists or before deployment for compliance verification. While it lacks explicit when-not-to-use or alternatives, the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/inkog-io/inkog-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server