The AI trust layer between agents: identity, agreements, safeguards, and outcome intelligence for A2A.
Commit 04c17739
04c1773999ceMerged
aryaamin <[email protected]> · 2 months ago · 8 files · ~8 modified
Description
feat: automate provider interaction finalization
Details
- Commit
- 04c1773999ce
- Parent
- 18b70a0f11a5
apps/api/src/app.tsmodifiedView file
@@ -325,10 +325,16 @@
325325
return getOnboardingState(repository, owner);326326
});327327
router.get('/v0.1/runtime/bootstrap', async (request) => {328-
operatorId(request);328+
const owner = operatorId(request);329329
const agentId = boundAgentId(request);330+
const rows = owner && repository ? await repository.list(owner) : [];331+
const profile = rows.find((row) => row.kind === 'agent_profile' && row.recordId === agentId)332+
?.payload as AgentProfile | undefined;330333
return {331334
agentId,335+
agentVersion: profile?.agentVersion ?? '1.0.0',336+
capabilities: profile?.capabilities ?? [],337+
limitations: profile?.limitations ?? [],332338
openClaspUrl: publicBaseUrl(request),333339
runtimeRegistrationEndpoint: `${publicBaseUrl(request)}/v0.1/runtime`,334340
protocol: 'A2A/1.0',@@ -356,6 +362,47 @@
356362
throw new Error('Agent presence is not configured');357363
return repository.touchAgentPresence(owner, boundAgentId(request));358364
});365+
router.put('/v0.1/runtime/profile', async (request) => {366+
const owner = operatorId(request);367+
if (!repository || !owner) throw new Error('Hosted persistence is not configured');368+
const agentId = boundAgentId(request);369+
const value = z370+
.object({371+
description: z.string().trim().max(500).optional(),372+
capabilities: z.array(z.string().trim().min(1).max(100)).min(1).max(100),373+
limitations: z.array(z.string().trim().min(1).max(300)).max(100).default([]),374+
})375+
.strict()376+
.parse(request.body);377+
const rows = await repository.list(owner);378+
const current = rows.find((row) => row.kind === 'agent_profile' && row.recordId === agentId)379+
?.payload as AgentProfile | undefined;380+
if (!current || current.status !== 'active') throw new Error('Active owned agent not found');381+
const profile: AgentProfile = {382+
...current,383+
...(value.description !== undefined ? { description: value.description } : {}),384+
capabilities: [...new Set(value.capabilities)],385+
limitations: [...new Set(value.limitations)],386+
updatedAt: new Date().toISOString(),387+
};388+
await repository.upsert(owner, 'agent_profile', agentId, profile);389+
const publication = rows.find((row) => row.kind === 'publication' && row.recordId === agentId)390+
?.payload as { published?: boolean } | undefined;391+
if (profile.autoPublish || publication?.published) {392+
const previous = await repository.getPublishedAgent(agentId);393+
const card = await repository.publishAgent(394+
owner,395+
buildPublicAgentCard(profile, publicBaseUrl(request), previous),396+
);397+
await repository.upsert(owner, 'publication', agentId, {398+
agentId,399+
published: true,400+
updatedAt: card.updatedAt,401+
});402+
return { profile, card };403+
}404+
return { profile };405+
});359406
router.post('/v0.1/onboarding/:id/approve', async (request) => {360407
const owner = operatorId(request);361408
if (!repository || !owner) throw new Error('Hosted persistence is not configured');@@ -404,8 +451,8 @@
404451
provider: z.enum(['botpress', 'custom']),405452
agentName: z.string().trim().min(1).max(100),406453
projectName: z.string().trim().min(1).max(100),407-
description: z.string().trim().max(500).optional(),408-
capabilities: z.array(z.string().trim().min(1).max(100)).max(100).default([]),454+
description: z.string().trim().min(1).max(500),455+
capabilities: z.array(z.string().trim().min(1).max(100)).min(1).max(100),409456
limitations: z.array(z.string().trim().min(1).max(300)).max(100).default([]),410457
expiresInDays: z.number().int().min(1).max(365).default(365),411458
})apps/dashboard/src/main.tsxmodifiedView file
Loading diff…
connectors/botpress/hub.mdmodifiedView file
Loading diff…
connectors/botpress/integration.definition.tsmodifiedView file
Loading diff…
connectors/botpress/package.jsonmodifiedView file
Loading diff…
connectors/botpress/src/index.tsmodifiedView file
Loading diff…
docs/CONNECTORS.mdmodifiedView file
Loading diff…
tests/api.test.tsmodifiedView file
Loading diff…