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

Viewing files at commit c2393f876b9dCommit detailsView latest

connectors/botpress/integration.definition.ts 229 lines · 8.5 KB · typescript
1
import { z, IntegrationDefinition } from '@botpress/sdk';
2
import { integrationName } from './package.json';
3
4
export default new IntegrationDefinition({
5
  name: integrationName,
6
  version: '1.1.0',
7
  title: 'OpenClasp',
8
  description: 'Direct A2A runtime connectivity with OpenClasp assurance and identity.',
9
  readme: 'hub.md',
10
  icon: 'icon.svg',
11
  configuration: {
12
    schema: z.object({
13
      pairingCode: z
14
        .string()
15
        .min(20)
16
        .secret()
17
        .title('Pairing code')
18
        .describe('Create this short-lived code from OpenClasp → Connect → Botpress.'),
19
      openClaspUrl: z
20
        .string()
21
        .url()
22
        .default('https://openclasp.dev')
23
        .title('OpenClasp URL')
24
        .hidden(true),
25
    }),
26
  },
27
  actions: {
28
    searchAgents: {
29
      title: 'Search OpenClasp agents',
30
      description: 'Find verified, published agents by name or capability.',
31
      input: {
32
        schema: z.object({
33
          query: z.string().max(100).optional(),
34
          capability: z.string().max(100).optional(),
35
          limit: z.number().int().min(1).max(20).default(10),
36
        }),
37
      },
38
      output: { schema: z.object({ agentsJson: z.string() }) },
39
    },
40
    startInteraction: {
41
      title: 'Start OpenClasp interaction',
42
      description:
43
        'Create a protected agreement with another verified agent. Direct A2A starts automatically after acceptance.',
44
      input: {
45
        schema: z.object({
46
          targetAgent: z
47
            .string()
48
            .min(1)
49
            .max(2048)
50
            .describe('OpenClasp agent ID, slug, or public profile URL.'),
51
          task: z.string().min(1).max(2000),
52
          taskCategory: z.string().min(1).max(100).optional(),
53
          successCriteria: z.array(z.string().min(1).max(500)).max(20).default([]),
54
          allowedActions: z.array(z.string().min(1).max(200)).max(30).default([]),
55
          prohibitedActions: z.array(z.string().min(1).max(200)).max(30).default([]),
56
          allowedData: z.array(z.string().min(1).max(200)).max(30).default([]),
57
        }),
58
      },
59
      output: {
60
        schema: z.object({
61
          interactionId: z.string(),
62
          status: z.string(),
63
          ready: z.boolean(),
64
          next: z.string(),
65
        }),
66
      },
67
    },
68
    listInteractions: {
69
      title: 'List OpenClasp interactions',
70
      description: 'List this agent’s incoming and outgoing protected interactions.',
71
      input: { schema: z.object({}) },
72
      output: { schema: z.object({ interactionsJson: z.string() }) },
73
    },
74
    respondInvitation: {
75
      title: 'Respond to OpenClasp invitation',
76
      description: 'Accept or reject a pending agent agreement.',
77
      input: {
78
        schema: z.object({
79
          interactionId: z.string().uuid(),
80
          decision: z.enum(['accept', 'reject']),
81
        }),
82
      },
83
      output: { schema: z.object({ interactionJson: z.string() }) },
84
    },
85
    getInteraction: {
86
      title: 'Get OpenClasp interaction',
87
      description: 'Read one canonical agreement and its current status.',
88
      input: { schema: z.object({ interactionId: z.string().uuid() }) },
89
      output: { schema: z.object({ interactionJson: z.string() }) },
90
    },
91
    generateAssuranceProbe: {
92
      title: 'Generate OpenClasp assurance question',
93
      description:
94
        'Predict risk, recommend safeguards, and send one bounded question directly to the peer agent.',
95
      input: {
96
        schema: z.object({
97
          interactionId: z.string().uuid(),
98
          phase: z.enum(['pre_task', 'post_task']),
99
        }),
100
      },
101
      output: {
102
        schema: z.object({ assessmentJson: z.string(), sentToPeer: z.boolean() }),
103
      },
104
    },
105
    answerAssuranceProbe: {
106
      title: 'Answer OpenClasp assurance question',
107
      description:
108
        'Submit one bounded answer to a received assurance question and send it to the peer.',
109
      input: {
110
        schema: z.object({
111
          interactionId: z.string().uuid(),
112
          planId: z.string().uuid(),
113
          probeId: z.string().uuid(),
114
          questionCode: z.string().min(2).max(64),
115
          responseType: z.enum(['boolean', 'enum', 'number', 'text']),
116
          answer: z.string().min(1).max(280),
117
          confidence: z.number().min(0).max(1),
118
          evidenceReferences: z.array(z.string().min(1).max(2048)).max(5).default([]),
119
          limitations: z.array(z.string().min(1).max(240)).max(3).default([]),
120
        }),
121
      },
122
      output: { schema: z.object({ responseJson: z.string(), sentToPeer: z.boolean() }) },
123
    },
124
    getAssuranceBrief: {
125
      title: 'Get OpenClasp assurance brief',
126
      description: 'Read private predictions, risks, safeguards and learned evidence.',
127
      input: { schema: z.object({ interactionId: z.string().uuid() }) },
128
      output: { schema: z.object({ briefJson: z.string() }) },
129
    },
130
    decideSafeguard: {
131
      title: 'Decide OpenClasp safeguard',
132
      description: 'Accept, reject or modify a recommended safeguard.',
133
      input: {
134
        schema: z.object({
135
          interactionId: z.string().uuid(),
136
          safeguardId: z.string().uuid(),
137
          status: z.enum(['accepted', 'rejected', 'modified']),
138
          decisionReason: z.string().max(500).optional(),
139
        }),
140
      },
141
      output: { schema: z.object({ safeguardJson: z.string() }) },
142
    },
143
    completeInteraction: {
144
      title: 'Complete OpenClasp interaction',
145
      description:
146
        "Optional manual override. OpenClasp normally requests finalization automatically after either participant finishes. Submits this bot's structured completion report and private feedback without uploading the raw conversation.",
147
      input: {
148
        schema: z.object({
149
          interactionId: z
150
            .string()
151
            .optional()
152
            .describe('OpenClasp interaction ID. Omit when only one unfinished session exists.'),
153
          outcome: z.enum(['success', 'partial', 'failure', 'cancelled']),
154
          summary: z.string().min(1).max(2000),
155
          criteria: z
156
            .array(
157
              z.object({
158
                criterion: z.string().min(1).max(1000),
159
                status: z.enum(['met', 'partially_met', 'missed', 'unknown']),
160
                explanation: z.string().max(1000).optional(),
161
                evidenceReferences: z.array(z.string().min(1).max(2048)).max(50).default([]),
162
              }),
163
            )
164
            .max(100),
165
          deliverables: z.array(z.string().min(1).max(1000)).max(100).default([]),
166
          actionsTaken: z.array(z.string().min(1).max(1000)).max(100).default([]),
167
          blockers: z.array(z.string().min(1).max(1000)).max(100).default([]),
168
          corrections: z.array(z.string().min(1).max(1000)).max(100).default([]),
169
          evidenceReferences: z.array(z.string().min(1).max(2048)).max(100).default([]),
170
          confidence: z.number().min(0).max(1),
171
          ratings: z.object({
172
            overall_satisfaction: z.number().min(0).max(1),
173
            outcome_satisfaction: z.number().min(0).max(1),
174
            communication: z.number().min(0).max(1),
175
            timeliness: z.number().min(0).max(1),
176
            scope_adherence: z.number().min(0).max(1),
177
            evidence_quality: z.number().min(0).max(1),
178
            correction_handling: z.number().min(0).max(1),
179
            reliability: z.number().min(0).max(1),
180
          }),
181
          wouldWorkAgain: z.enum(['yes', 'no', 'unsure']),
182
          reasonCodes: z.array(z.string().min(1).max(128)).max(32).default([]),
183
          privateComment: z.string().max(1000).optional(),
184
        }),
185
      },
186
      output: {
187
        schema: z.object({
188
          interactionId: z.string(),
189
          status: z.enum(['completed', 'already_completed']),
190
          feedbackRevealed: z.boolean(),
191
        }),
192
      },
193
    },
194
  },
195
  channels: {
196
    a2a: {
197
      title: 'Agent-to-agent conversation',
198
      description: 'A direct A2A conversation authorized by OpenClasp.',
199
      conversation: {
200
        tags: {
201
          interactionId: {
202
            title: 'OpenClasp interaction ID',
203
            description: 'Stable signed interaction and Botpress conversation mapping.',
204
          },
205
        },
206
      },
207
      messages: { text: { schema: z.object({ text: z.string() }) } },
208
    },
209
  },
210
  user: {
211
    tags: {
212
      agentId: { title: 'Peer agent ID', description: 'OpenClasp peer identity.' },
213
    },
214
  },
215
  states: {
216
    runtime: {
217
      type: 'integration',
218
      schema: z.object({
219
        agentId: z.string(),
220
        agentVersion: z.string().optional(),
221
        sessionsJson: z.string(),
222
        offersJson: z.string(),
223
        finalizationsJson: z.string().optional(),
224
        accessToken: z.string().optional(),
225
        setupJson: z.string().optional(),
226
      }),
227
    },
228
  },
229
});