import { openai } from '@ai-sdk/openai';
import { Agent } from '@mastra/core/agent';
import { createTool } from '@mastra/core/tools';
import { z } from 'zod';
import {
Configuration,
PactsApi,
TransactionRecordsApi,
TransactionsApi,
} from '@cobo/agentic-wallet';
const config = new Configuration({
apiKey: process.env.AGENT_WALLET_API_KEY!,
basePath: process.env.AGENT_WALLET_API_URL!,
});
const pactsApi = new PactsApi(config);
const txApi = new TransactionsApi(config);
const recordsApi = new TransactionRecordsApi(config);
async function returnPolicyDenial<T>(work: () => Promise<T>) {
try {
return await work();
} catch (error) {
return (error as {
response?: { data?: { error?: Record<string, unknown> } };
}).response?.data?.error ?? { error: 'UNKNOWN_ERROR' };
}
}
const submitPactTool = createTool({
id: 'submit-pact',
description: 'Submit a pact and return the pact id.',
inputSchema: z.object({
wallet_id: z.string(),
intent: z.string(),
}),
execute: async ({ context }) => {
const response = await pactsApi.submitPact({
wallet_id: context.wallet_id,
intent: context.intent,
spec: {
completion_conditions: [{ type: 'time_elapsed', threshold: '86400' }],
},
});
return response.data.result;
},
});
const contractCallTool = createTool({
id: 'contract-call',
description: 'Execute a policy-enforced contract call.',
inputSchema: z.object({
wallet_uuid: z.string(),
contract_addr: z.string(),
calldata: z.string(),
request_id: z.string(),
}),
execute: async ({ context }) => {
return await returnPolicyDenial(async () => {
const response = await txApi.contractCall(context.wallet_uuid, {
chain_id: 'BASE_ETH',
contract_addr: context.contract_addr,
calldata: context.calldata,
value: '0',
request_id: context.request_id,
});
return response.data.result;
});
},
});
const recordTool = createTool({
id: 'get-transaction-record-by-request-id',
description: 'Look up a transaction record by request id.',
inputSchema: z.object({
wallet_uuid: z.string(),
request_id: z.string(),
}),
execute: async ({ context }) => {
const response = await recordsApi.getTransactionRecordByRequestId(
context.wallet_uuid,
context.request_id,
);
return response.data.result;
},
});
const agent = new Agent({
name: 'cobo-operator',
model: openai('gpt-4.1-mini'),
instructions:
'Before executing blockchain actions, submit a pact and wait until it is active. If a tool returns a policy denial, read the suggestion and retry with compliant params. After submission, track the result by request_id.',
tools: { submitPactTool, contractCallTool, recordTool },
});