-
Notifications
You must be signed in to change notification settings - Fork 157
Expand file tree
/
Copy pathindex.ts
More file actions
136 lines (125 loc) · 4.24 KB
/
Copy pathindex.ts
File metadata and controls
136 lines (125 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import express from 'express';
import { Server, ServerCredentials } from '@grpc/grpc-js';
import { A2A_PROTOCOL_VERSION, AGENT_CARD_PATH, AgentCard } from '../../../index.js';
import {
InMemoryTaskStore,
TaskStore,
AgentExecutor,
DefaultRequestHandler,
} from '../../../server/index.js';
import {
agentCardHandler,
jsonRpcHandler,
restHandler,
UserBuilder,
} from '../../../server/express/index.js';
import { grpcService, A2AService } from '../../../server/grpc/index.js';
import { SampleAgentExecutor } from '../sample-agent/agent_executor.js';
// --- Configuration ---
const HTTP_PORT = Number(process.env.HTTP_PORT || 41241);
const GRPC_PORT = Number(process.env.GRPC_PORT || 41242);
// --- Agent Card ---
//
// Lists all three protocol bindings exposed by this agent so that A2A clients
// can pick whichever transport they prefer. `ClientFactory.createFromAgentCard`
// chooses the highest-priority interface that matches a registered transport
// factory on the client.
const multiTransportAgentCard: AgentCard = {
name: 'Sample Multi-Transport Agent',
description:
'A sample agent exposing the same A2A surface over JSON-RPC, HTTP+JSON ' +
'REST, and gRPC simultaneously.',
supportedInterfaces: [
{
url: `http://localhost:${HTTP_PORT}/a2a/jsonrpc`,
protocolBinding: 'JSONRPC',
tenant: '',
protocolVersion: A2A_PROTOCOL_VERSION,
},
{
url: `http://localhost:${HTTP_PORT}/a2a/rest`,
protocolBinding: 'HTTP+JSON',
tenant: '',
protocolVersion: A2A_PROTOCOL_VERSION,
},
{
url: `localhost:${GRPC_PORT}`,
protocolBinding: 'GRPC',
tenant: '',
protocolVersion: A2A_PROTOCOL_VERSION,
},
],
provider: {
organization: 'A2A Samples',
url: 'https://example.com/a2a-samples',
},
version: '1.0.0',
capabilities: {
streaming: true,
pushNotifications: false,
extensions: [],
extendedAgentCard: false,
},
securitySchemes: {},
securityRequirements: [],
defaultInputModes: ['text'],
defaultOutputModes: ['text', 'task-status'],
skills: [
{
id: 'sample_agent',
name: 'Sample Agent',
description: 'Reuses the SampleAgentExecutor across all transports.',
tags: ['sample', 'multi-transport'],
examples: ['hi', 'hello', 'how are you'],
inputModes: ['text'],
outputModes: ['text', 'task-status'],
securityRequirements: [],
},
],
documentationUrl: '',
signatures: [],
};
async function main() {
// 1. Shared infrastructure: one TaskStore, one AgentExecutor, one
// DefaultRequestHandler. All three transport handlers are thin adapters
// over this single request handler instance.
const taskStore: TaskStore = new InMemoryTaskStore();
const agentExecutor: AgentExecutor = new SampleAgentExecutor();
const requestHandler = new DefaultRequestHandler(
multiTransportAgentCard,
taskStore,
agentExecutor
);
// 2. Express app: JSON-RPC + REST + AgentCard.
const app = express();
app.use(`/${AGENT_CARD_PATH}`, agentCardHandler({ agentCardProvider: requestHandler }));
app.use(
'/a2a/jsonrpc',
jsonRpcHandler({ requestHandler, userBuilder: UserBuilder.noAuthentication })
);
app.use('/a2a/rest', restHandler({ requestHandler, userBuilder: UserBuilder.noAuthentication }));
app.listen(HTTP_PORT, (err) => {
if (err) {
throw err;
}
console.log(`[MultiTransportAgent] HTTP server started on http://localhost:${HTTP_PORT}`);
console.log(` JSON-RPC : http://localhost:${HTTP_PORT}/a2a/jsonrpc`);
console.log(` REST : http://localhost:${HTTP_PORT}/a2a/rest`);
console.log(` Card : http://localhost:${HTTP_PORT}/${AGENT_CARD_PATH}`);
});
// 3. gRPC server on a separate port.
const grpcServer = new Server();
grpcServer.addService(
A2AService,
grpcService({ requestHandler, userBuilder: UserBuilder.noAuthentication })
);
grpcServer.bindAsync(`localhost:${GRPC_PORT}`, ServerCredentials.createInsecure(), (err) => {
if (err) {
console.error(`[MultiTransportAgent] gRPC bind failed:`, err);
return;
}
console.log(`[MultiTransportAgent] gRPC server started on localhost:${GRPC_PORT}`);
});
console.log('[MultiTransportAgent] Press Ctrl+C to stop the server');
}
main().catch(console.error);