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

Viewing files at commit 8a15fe87b720Commit detailsView latest

tests/quickstart-api.test.ts 157 lines · 5.7 KB · typescript
1
import { describe, expect, it } from 'vitest';
2
import { buildApi } from '../apps/api/src/app.js';
3
import { buildPublicAgentCard } from '../packages/persistence/src/hosted.js';
4
import type { AgentProfile } from '../packages/persistence/src/onboarding.js';
5
import type {
6
  FeedbackRequest,
7
  FederatedInteraction,
8
  PublicAgentCard,
9
} from '../packages/protocol/src/index.js';
10
11
describe('dashboard quickstart API', () => {
12
  it('creates an agent, starts an agreement, and records owner outcome and feedback', async () => {
13
    const rows: { kind: string; recordId: string; payload: any }[] = [];
14
    const cards = new Map<string, PublicAgentCard>();
15
    let interaction: FederatedInteraction | undefined;
16
    let feedbackRequest: FeedbackRequest | undefined;
17
    const peerProfile: AgentProfile = {
18
      agentId: 'agent-peer',
19
      projectId: 'project-peer',
20
      name: 'Peer runtime',
21
      description: 'Does product research',
22
      framework: 'Custom runtime',
23
      agentVersion: '1.0.0',
24
      agentMode: 'persistent_runtime',
25
      a2aEndpoint: 'https://peer.example/a2a',
26
      transport: 'direct_a2a',
27
      autoPublish: true,
28
      autoAcceptPolicy: 'off',
29
      autoAcceptTaskCategories: [],
30
      capabilities: ['research'],
31
      limitations: [],
32
      identityMode: 'owner_managed',
33
      status: 'active',
34
      createdAt: '2026-08-31T10:00:00.000Z',
35
      updatedAt: '2026-08-31T10:00:00.000Z',
36
    };
37
    cards.set('agent-peer', buildPublicAgentCard(peerProfile, 'https://openclasp.example'));
38
    const repository = {
39
      list: async () => rows,
40
      upsert: async (_operatorId: string, kind: string, recordId: string, payload: any) => {
41
        const current = rows.find((row) => row.kind === kind && row.recordId === recordId);
42
        if (current) current.payload = payload;
43
        else rows.push({ kind, recordId, payload });
44
      },
45
      publishAgent: async (_operatorId: string, card: PublicAgentCard) => {
46
        cards.set(card.agentId, card);
47
        return card;
48
      },
49
      getPublishedAgent: async (agentId: string) => cards.get(agentId),
50
      createFederatedInteraction: async (_operatorId: string, value: FederatedInteraction) => {
51
        interaction = value;
52
        return value;
53
      },
54
      getFederatedInteraction: async () => interaction,
55
      getLiveSession: async () => ({ activatedAt: '2026-08-31T10:01:00.000Z' }),
56
      submitCompletionReport: async (
57
        _operatorId: string,
58
        _agentId: string,
59
        report: any,
60
        method: string,
61
      ) => {
62
        rows.push({ kind: 'completion_report', recordId: report.reportId, payload: report });
63
        feedbackRequest = {
64
          requestId: '33333333-3333-4333-8333-333333333333',
65
          interactionId: report.interactionId,
66
          reviewerAgentId: report.reportingAgentId,
67
          subjectAgentId: report.counterpartyAgentId,
68
          status: 'pending',
69
          requestedDimensions: ['overall_satisfaction'],
70
          requestedAt: '2026-08-31T10:02:00.000Z',
71
          dueAt: '2026-09-01T10:02:00.000Z',
72
        };
73
        return { report, method };
74
      },
75
      listFeedbackRequests: async () => (feedbackRequest ? [feedbackRequest] : []),
76
      submitInteractionFeedback: async (
77
        _operatorId: string,
78
        _agentId: string,
79
        feedback: any,
80
        method: string,
81
      ) => ({ feedback, method }),
82
    } as any;
83
    const app = buildApi(undefined, undefined, repository);
84
    await app.ready();
85
    const headers = { 'x-openclasp-operator': 'owner-a' };
86
87
    const createdResponse = await app.inject({
88
      method: 'POST',
89
      url: '/v0.1/quickstart/agent',
90
      headers,
91
      payload: {
92
        agentName: 'Research assistant',
93
        projectName: 'My agents',
94
        description: 'Returns sourced comparisons',
95
        capabilities: ['research'],
96
      },
97
    });
98
    expect(createdResponse.statusCode).toBe(200);
99
    const created = createdResponse.json();
100
    expect(created.card).toMatchObject({
101
      agentMode: 'temporary_chat',
102
      transports: [{ managedBy: 'openclasp' }],
103
    });
104
105
    const startedResponse = await app.inject({
106
      method: 'POST',
107
      url: '/v0.1/federated-interactions/start',
108
      headers,
109
      payload: {
110
        initiatorAgentId: created.agent.agentId,
111
        responderAgentId: 'agent-peer',
112
        task: 'Compare three customer support platforms',
113
        requestedOutcome: 'A ranked shortlist',
114
        successCriterion: 'Three current products with source links',
115
      },
116
    });
117
    expect(startedResponse.statusCode).toBe(200);
118
    expect(startedResponse.json()).toMatchObject({
119
      status: 'pending',
120
      acceptances: { [created.agent.agentId]: { method: 'oauth_account' } },
121
    });
122
    interaction = { ...interaction!, status: 'active' };
123
124
    const completedResponse = await app.inject({
125
      method: 'POST',
126
      url: `/v0.1/federated-interactions/${interaction.interactionId}/complete`,
127
      headers,
128
      payload: {
129
        agentId: created.agent.agentId,
130
        outcome: 'success',
131
        summary: 'Delivered a ranked, sourced shortlist.',
132
      },
133
    });
134
    expect(completedResponse.statusCode).toBe(200);
135
    expect(completedResponse.json()).toMatchObject({
136
      method: 'oauth_account',
137
      report: { submissionMethod: 'oauth_account' },
138
    });
139
140
    const feedbackResponse = await app.inject({
141
      method: 'POST',
142
      url: `/v0.1/feedback-requests/${feedbackRequest!.requestId}/respond`,
143
      headers,
144
      payload: {
145
        agentId: created.agent.agentId,
146
        rating: 5,
147
        wouldWorkAgain: 'yes',
148
      },
149
    });
150
    expect(feedbackResponse.statusCode).toBe(200);
151
    expect(feedbackResponse.json()).toMatchObject({
152
      method: 'oauth_account',
153
      feedback: { ratings: { overall_satisfaction: 1 } },
154
    });
155
    await app.close();
156
  });
157
});