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

Viewing files at commit 922a6b480fb8Commit detailsView latest

tests/agent-card-onboarding.test.ts 78 lines · 2.9 KB · typescript
1
import { describe, expect, it } from 'vitest';
2
import { buildApi } from '../apps/api/src/app.js';
3
import type { PublicAgentCard } from '../packages/protocol/src/index.js';
4
5
describe('Agent Card onboarding API', () => {
6
  it('creates a private external profile and publishes it only after confirmation', async () => {
7
    const rows: { kind: string; recordId: string; payload: any }[] = [];
8
    const cards = new Map<string, PublicAgentCard>();
9
    const repository = {
10
      list: async () => rows,
11
      upsert: async (_operatorId: string, kind: string, recordId: string, payload: any) => {
12
        const current = rows.find((row) => row.kind === kind && row.recordId === recordId);
13
        if (current) current.payload = payload;
14
        else rows.push({ kind, recordId, payload });
15
      },
16
      publishAgent: async (_operatorId: string, card: PublicAgentCard) => {
17
        cards.set(card.agentId, card);
18
        return card;
19
      },
20
      unpublishAgent: async (_operatorId: string, agentId: string) => cards.delete(agentId),
21
      getPublishedAgent: async (agentId: string) => cards.get(agentId),
22
    } as any;
23
    const app = buildApi(undefined, undefined, repository);
24
    await app.ready();
25
    const headers = { 'x-openclasp-operator': 'owner-a' };
26
27
    const createdResponse = await app.inject({
28
      method: 'POST',
29
      url: '/v0.1/quickstart/agent',
30
      headers,
31
      payload: {
32
        agentName: 'Research assistant',
33
        projectName: 'My agents',
34
        description: 'Returns sourced comparisons',
35
        framework: 'LangGraph',
36
        capabilities: ['research'],
37
      },
38
    });
39
    expect(createdResponse.statusCode).toBe(200);
40
    const created = createdResponse.json();
41
    expect(created).not.toHaveProperty('card');
42
    expect(created.agent).toMatchObject({
43
      framework: 'LangGraph',
44
      agentMode: 'persistent_runtime',
45
      transport: 'direct_a2a',
46
      autoPublish: false,
47
    });
48
    expect(cards.size).toBe(0);
49
50
    const publicationResponse = await app.inject({
51
      method: 'POST',
52
      url: `/v0.1/agents/${created.agent.agentId}/publication`,
53
      headers,
54
      payload: { published: true },
55
    });
56
    expect(publicationResponse.statusCode).toBe(200);
57
    expect(publicationResponse.json()).toMatchObject({
58
      published: true,
59
      profileUrl: expect.stringContaining('/a/'),
60
      cardUrl: expect.stringContaining('/card.json'),
61
      verification: { status: 'verified', method: 'openclasp_oauth_account' },
62
      card: {
63
        agentMode: 'persistent_runtime',
64
        transports: [],
65
        assurance: 'oauth_authenticated',
66
      },
67
    });
68
    expect(
69
      rows.find((row) => row.kind === 'publication' && row.recordId === created.agent.agentId)
70
        ?.payload,
71
    ).toMatchObject({
72
      published: true,
73
      profileUrl: expect.stringContaining('/a/'),
74
      cardUrl: expect.stringContaining('/card.json'),
75
    });
76
    await app.close();
77
  });
78
});