The AI trust layer between agents: identity, agreements, safeguards, and outcome intelligence for A2A.

Viewing files at commit fd993cf6d9f8Commit detailsView latest

tests/automation.test.ts 106 lines · 3.3 KB · typescript
1
import { describe, expect, it } from 'vitest';
2
import { canonicalHash, type FederatedInteraction } from '@openclasp/protocol';
3
import { canAutoAcceptInteraction } from '../packages/persistence/src/hosted.js';
4
import type { AgentProfile } from '../packages/persistence/src/onboarding.js';
5
6
function fixture(): { agent: AgentProfile; interaction: FederatedInteraction } {
7
  const interactionId = crypto.randomUUID();
8
  const now = new Date().toISOString();
9
  const contract = {
10
    protocolVersion: '0.1' as const,
11
    interactionId,
12
    purpose: 'Research a competitor',
13
    parties: ['agent:a', 'agent:b'],
14
    taskCategory: 'research',
15
    requestedOutcome: 'A short brief',
16
    successCriteria: ['Directly answer the task'],
17
    allowedActions: [],
18
    prohibitedActions: [],
19
    allowedData: [],
20
    prohibitedData: [],
21
    evidenceRequirements: [],
22
    delegationRules: ['explicit_contract_scope'],
23
    humanApprovalRequirements: [],
24
    factCheckingPolicy: 'important_claims',
25
    mediationPolicy: 'mutual_consent' as const,
26
    retentionDays: 30,
27
    completionConditions: ['Directly answer the task'],
28
    cancellationConditions: ['either_party_before_completion'],
29
    signatures: {},
30
  };
31
  const termsHash = canonicalHash(contract);
32
  return {
33
    agent: {
34
      agentId: 'agent:b',
35
      projectId: 'project:b',
36
      name: 'Research agent',
37
      description: '',
38
      framework: 'Codex',
39
      agentVersion: '1.0.0',
40
      a2aEndpoint: 'https://agent-b.example/a2a',
41
      autoPublish: true,
42
      autoAcceptPolicy: 'safe_matching',
43
      autoAcceptTaskCategories: ['research'],
44
      capabilities: ['research'],
45
      limitations: [],
46
      identityMode: 'oauth_installation',
47
      status: 'active',
48
      createdAt: now,
49
      updatedAt: now,
50
    },
51
    interaction: {
52
      protocolVersion: '0.1',
53
      interactionId,
54
      initiatorAgentId: 'agent:a',
55
      responderAgentId: 'agent:b',
56
      status: 'pending',
57
      contract,
58
      termsHash,
59
      acceptances: {
60
        'agent:a': {
61
          agentId: 'agent:a',
62
          method: 'oauth_installation',
63
          termsHash,
64
          acceptedAt: now,
65
        },
66
      },
67
      responderTransport: {
68
        protocol: 'A2A/1.0',
69
        protocolBinding: 'JSONRPC',
70
        endpoint: 'https://agent-b.example/a2a',
71
        managedBy: 'openclasp',
72
      },
73
      createdAt: now,
74
      updatedAt: now,
75
      expiresAt: new Date(Date.now() + 60_000).toISOString(),
76
    },
77
  };
78
}
79
80
describe('safe connection automation', () => {
81
  it('auto-accepts only matching, data-free requests within the owner policy', () => {
82
    const { agent, interaction } = fixture();
83
    expect(canAutoAcceptInteraction(agent, interaction)).toBe(true);
84
    expect(
85
      canAutoAcceptInteraction(agent, {
86
        ...interaction,
87
        contract: { ...interaction.contract, allowedData: ['customer_records'] },
88
      }),
89
    ).toBe(false);
90
    expect(
91
      canAutoAcceptInteraction(agent, {
92
        ...interaction,
93
        contract: { ...interaction.contract, purpose: 'Find a customer access token' },
94
      }),
95
    ).toBe(false);
96
    expect(
97
      canAutoAcceptInteraction(agent, {
98
        ...interaction,
99
        contract: { ...interaction.contract, taskCategory: 'payments' },
100
      }),
101
    ).toBe(false);
102
    expect(canAutoAcceptInteraction({ ...agent, autoAcceptPolicy: 'off' }, interaction)).toBe(
103
      false,
104
    );
105
  });
106
});