import { z } from 'zod';
import type { RegistryApiClient } from '../client/api.js';
import { verify as verifySig } from '../crypto/signing.js';
export const verifyInputSchema = z.object({
message: z.string().describe('The original message that was signed'),
signature: z.string().describe('The signature to verify (base64)'),
origin: z.string().describe('The origin/domain claiming to have signed the message'),
keyId: z.string().uuid().optional().describe('Specific key ID to verify against'),
localOnly: z.boolean().optional().describe('If true, verify locally without contacting registry'),
publicKey: z.string().optional().describe('Public key for local verification (required if localOnly=true)'),
});
export type VerifyInput = z.infer<typeof verifyInputSchema>;
export interface VerifyResult {
valid: boolean;
agent?: {
id: string;
name: string;
origin: string | null;
};
key?: {
id: string;
status: string;
label: string | null;
};
method: 'registry' | 'local';
error?: string;
}
/**
* Verify a signature from another agent.
*
* Can verify either:
* - Via registry (default): Looks up the agent's public key and verifies
* - Locally: Uses provided public key (for offline verification)
*/
export async function verify(
input: VerifyInput,
client: RegistryApiClient
): Promise<VerifyResult> {
// Local verification
if (input.localOnly) {
if (!input.publicKey) {
return {
valid: false,
method: 'local',
error: 'publicKey is required for local verification',
};
}
try {
const isValid = await verifySig(input.message, input.signature, input.publicKey);
return {
valid: isValid,
method: 'local',
error: isValid ? undefined : 'Signature verification failed',
};
} catch (error) {
return {
valid: false,
method: 'local',
error: error instanceof Error ? error.message : 'Verification error',
};
}
}
// Registry verification
try {
const result = await client.verify({
message: input.message,
signature: input.signature,
origin: input.origin,
keyId: input.keyId,
});
return {
valid: result.valid,
method: 'registry',
agent: result.agent
? {
id: result.agent.id,
name: result.agent.name,
origin: result.agent.domain,
}
: undefined,
key: result.key
? {
id: result.key.id,
status: result.key.status,
label: result.key.label,
}
: undefined,
error: result.error,
};
} catch (error) {
return {
valid: false,
method: 'registry',
error: error instanceof Error ? error.message : 'Verification failed',
};
}
}
export const verifyTool = {
name: 'agents_registry_verify',
description: 'Verify that a message was signed by a specific agent. Can verify via the registry or locally with a known public key.',
inputSchema: {
type: 'object' as const,
properties: {
message: {
type: 'string',
description: 'The original message that was signed',
},
signature: {
type: 'string',
description: 'The signature to verify (base64 encoded)',
},
origin: {
type: 'string',
description: 'The origin/domain claiming to have signed the message',
},
keyId: {
type: 'string',
description: 'Specific key ID to verify against (optional)',
},
localOnly: {
type: 'boolean',
description: 'If true, verify locally without contacting the registry',
},
publicKey: {
type: 'string',
description: 'Public key for local verification (required if localOnly=true)',
},
},
required: ['message', 'signature', 'origin'],
},
};