Upstreet Docs
    Integrations

    Connect external agents to Upstreet NPCs via Google's Agent-to-Agent protocol for agent interoperability.

    A2A (Agent-to-Agent) Integration

    Every Upstreet NPC is exposed as an A2A-compatible agent—ready to chat, reason, and collaborate with external AI systems out of the box.


    What is A2A?

    Agent-to-Agent (A2A) is Google's open protocol for agent interoperability. It lets different AI agents discover each other, exchange structured messages, and invoke skills in a standardized way. Upstreet uses A2A so your NPCs can participate in multi-agent workflows, be controlled by external orchestrators, or serve as conversational interfaces from any compatible client.

    A2A enables true agent-to-agent communication—not just human-to-agent. Your NPC can talk to other A2A agents, tools, and systems without custom integrations.


    Endpoints

    GET /api/a2a/{npcId}/.well-known/agent-card.json

    Returns the agent card—a JSON document describing the NPC's capabilities, transport URLs, and authentication requirements. Use this for discovery before connecting.

    POST /api/a2a/{npcId}/jsonrpc

    The JSON-RPC transport endpoint. Send A2A messages here to converse with the NPC, invoke skills, and receive responses.


    Authentication

    Both endpoints require authentication. Pass your API key or Supabase JWT as a Bearer token:

    Authorization: Bearer <your-token>

    You can only interact with NPCs you own. The token identifies the caller; the NPC must belong to your account.


    Quick Start with @a2a-js/sdk

    Install the SDK

    npm install @a2a-js/sdk

    Create a Client

    import { ClientFactory } from '@a2a-js/sdk/client';
    import type { MessageSendParams } from '@a2a-js/sdk';
    
    const factory = new ClientFactory();
    const npcId = 'your-npc-id';
    const baseUrl = `https://upstreet.ai/api/a2a/${npcId}`;
    
    const client = await factory.createFromUrl(baseUrl, undefined);

    Send a Message

    const result = await client.sendMessage({
      message: {
        kind: 'message',
        messageId: crypto.randomUUID(),
        role: 'user',
        parts: [{ kind: 'text', text: 'Hello! Who are you?' }],
      },
      configuration: {
        blocking: true,
        acceptedOutputModes: ['text/plain'],
      },
    });

    Full Code Example

    import { ClientFactory } from '@a2a-js/sdk/client';
    import type { MessageSendParams } from '@a2a-js/sdk';
    
    const factory = new ClientFactory();
    const npcId = 'your-npc-id';
    const baseUrl = `https://upstreet.ai/api/a2a/${npcId}`;
    
    const client = await factory.createFromUrl(baseUrl, undefined);
    
    const result = await client.sendMessage({
      message: {
        kind: 'message',
        messageId: crypto.randomUUID(),
        role: 'user',
        parts: [{ kind: 'text', text: 'Hello! Who are you?' }],
      },
      configuration: {
        blocking: true,
        acceptedOutputModes: ['text/plain'],
      },
    });

    You must pass your API key when creating the client—typically via fetch options or a custom transport that adds the Authorization: Bearer <token> header to requests.


    Message Flow

    sequenceDiagram
        participant Client
        participant A2A as Upstreet A2A API
        participant NPC as NPC Engine
        participant AI as AI (Mastra)
    
        Client->>A2A: GET /.well-known/agent-card.json
        A2A-->>Client: Agent card (name, skills, url)
    
        Client->>A2A: POST /jsonrpc (sendMessage)
        A2A->>NPC: Route to NPC by id
        NPC->>AI: Generate response
        AI-->>NPC: Reply text
        NPC-->>A2A: A2A message (agent role)
        A2A-->>Client: JSON-RPC response

    Agent Card Structure

    The agent card describes your NPC's capabilities and how to connect:

    FieldDescription
    nameNPC display name
    descriptionShort description of the agent
    protocolVersionA2A protocol version (e.g. 0.3.0)
    urlJSON-RPC transport URL
    preferredTransportJSONRPC
    skillsAvailable skills (e.g. chat)
    capabilitiesStreaming, push notifications, etc.
    defaultInputModes["text/plain"]
    defaultOutputModes["text/plain"]
    securitySchemesbearerAuth (JWT)
    security[{ bearerAuth: [] }]

    Explore More