halfengineer

Buildingagents,shippingcode.

Developer Advocate · AI Agent Engineer · Community Builder

Bridging the Gap: Building Web Applications with Fetch.ai uAgents and Agentverse

Gautam Manak December 15, 2024 5 min read

Understanding the Challenge

The world of decentralized AI agents is rapidly evolving, and Fetch.ai's uAgents framework stands at the forefront of this revolution. However, integrating these powerful Python-based agents into modern JavaScript and TypeScript applications has traditionally been a complex challenge. The uAgent Client library changes this narrative entirely, providing a seamless bridge between your Node.js or web applications and the Fetch.ai ecosystem, complete with automatic Agentverse integration.

When developers want to integrate Fetch.ai uAgents into their applications, they face a fundamental architectural challenge. uAgents are built using Python and communicate through specialized protocols that aren't natively accessible from JavaScript environments. The uAgent Client library eliminates all of this complexity by providing a production-ready solution.

Prerequisites

Before you begin, ensure you have:

  • Node.js 18+ installed
  • Python 3.8+ installed (for bridge agent)
  • Basic knowledge of JavaScript/TypeScript
  • Agentverse Token (optional, for agent registration)

Installation

1. Install the Package

npm install uagent-client

2. Install Python Dependencies (Optional)

pip install uagents uagents-core requests

The Architecture Behind the Magic

The uAgent Client architecture consists of four primary components working in harmony. Your application uses the uAgent Client library to send queries. The client library communicates with a Python bridge agent that runs as a separate process, handling all the complex protocol interactions. This bridge agent then communicates with the target uAgent using Fetch.ai's chat protocol, and responses flow back through the same chain in reverse.

What makes this architecture particularly powerful is its integration with Fetch.ai's Agentverse platform. When you create a bridge agent with the uAgent Client, it automatically registers itself with Agentverse, making it discoverable and enabling seamless communication with other agents on the network.

Per-User Isolation

One of the most powerful features of the uAgent Client is its support for per-user bridge agents. In a multi-user application, you can create isolated bridge agents for each user session, ensuring complete separation of user data and communication channels.

Getting Started

JavaScript Example

const UAgentClient = require('uagent-client');

const client = new UAgentClient();

const result = await client.query(
    'agent1q2g97humd4d6mgmcg783s2dsncu8hn37r3sgglu6eqa6es07wk3xqlmmy4v',
    'Search for pizza restaurants in New York'
);

if (result.success) {
    console.log(result.response);
} else {
    console.error(result.error);
}

TypeScript Example

import UAgentClient from 'uagent-client';

const client = new UAgentClient();

const result = await client.query(
    'agent1q2g97humd4d6mgmcg783s2dsncu8hn37r3sgglu6eqa6es07wk3xqlmmy4v',
    'Search for pizza restaurants in New York'
);

if (result.success) {
    console.log(result.response);
} else {
    console.error(result.error);
}

Per-User Bridge Setup

const UAgentClient = require('uagent-client');

const client = new UAgentClient({
    userSeed: 'user-123',
    agentverseToken: 'your-bearer-token'
});

await client.createUserBridge('user-123', 'bearer-token');

Simple Method (Returns String Directly)

const client = new UAgentClient();

try {
    const response = await client.ask('agent_address', 'Your question');
    console.log(response);
} catch (error) {
    console.error('Failed:', error.message);
}

Production Implementation

Next.js API Route Example

// app/api/chat/route.ts
import { NextRequest, NextResponse } from 'next/server';

const UAGENT_ADDRESS = 'agent1qfaar64uhcx6ct3ufyerl7csaytwsezwxekeukrwp3667fg8nl05c9fmze7';
const AGENTVERSE_TOKEN = 'your-bearer-token-here';
const USER_SEED = 'gautam';

const clientInstances = new Map<string, any>();

async function getClient(seed: string, token: string) {
  if (!clientInstances.has(seed)) {
    const UAgentClientModule = await import('uagent-client');
    const UAgentClient = UAgentClientModule.default || UAgentClientModule;

    const config: any = {
      timeout: 60000,
      autoStartBridge: true,
      userSeed: seed,
      agentverseToken: token
    };

    const client = new (UAgentClient as any)(config);
    await client.createUserBridge(seed, token);

    clientInstances.set(seed, client);
    await new Promise(resolve => setTimeout(resolve, 3000));
  }

  return clientInstances.get(seed);
}

export async function POST(request: NextRequest) {
  try {
    const { message, userSeed, agentverseToken } = await request.json();
    if (!message || typeof message !== 'string') {
      return NextResponse.json({ error: 'Invalid message' }, { status: 400 });
    }

    const client = await getClient(
      userSeed || USER_SEED,
      agentverseToken || AGENTVERSE_TOKEN
    );

    const result = await client.query(UAGENT_ADDRESS, message);

    if (result.success) {
      return NextResponse.json({ response: result.response, success: true });
    } else {
      return NextResponse.json({
        response: 'Unable to process your request at this time.',
        success: false,
        error: result.error
      });
    }
  } catch (error) {
    return NextResponse.json(
      { response: 'An error occurred.', error: error instanceof Error ? error.message : 'Unknown error' },
      { status: 500 }
    );
  }
}

Configuration

Client Options

new UAgentClient({
    timeout?: number,           // Default: 35000ms
    bridgeUrl?: string,          // Default: 'http://localhost:8000'
    autoStartBridge?: boolean,   // Default: true
    userSeed?: string,           // For per-user bridges
    agentverseToken?: string     // For Agentverse registration
})

Deployment

Platform Compatibility

Not Supported:

  • Vercel — Serverless platform, requires persistent Python processes
  • Netlify — Serverless platform, requires backend services

Recommended for Production:

  • Docker — Container-based deployment
  • Render — Full platform with Docker support
  • AWS ECS/EC2 — Container and VM support
  • Google Cloud Run/GKE — Container platforms
  • DigitalOcean — App Platform or Droplets
  • Railway — Supports persistent processes

Docker Deployment

FROM node:18-slim

WORKDIR /app

RUN apt-get update && apt-get install -y \
    python3 python3-pip gcc g++ \
    && ln -s /usr/bin/python3 /usr/bin/python \
    && rm -rf /var/lib/apt/lists/*

COPY package*.json ./
RUN npm install
COPY . .

RUN pip3 install --no-cache-dir --break-system-packages uagents uagents-core requests

EXPOSE 3000

CMD ["sh", "-c", "if [ -f node_modules/uagent-client/bridge_agent.py ]; then python3 node_modules/uagent-client/bridge_agent.py & fi && npm run dev"]

API Reference

Methods

query(agentAddress, query, requestId?)

Returns:

{
    success: boolean,
    response?: string,
    error?: string,
    requestId: string
}

ask(agentAddress, query)

Returns: Promise<string> — throws error if fails.

createUserBridge(seed, token, port?)

const bridgeInfo = await client.createUserBridge(
    'user-123',           // Unique seed for user
    'bearer-token',       // Agentverse bearer token
    8001                  // Optional port
);
// Returns: { name, address, port, seed }

Security Best Practices

// DON'T: Expose token in client code
const token = 'bearer-token';

// DO: Keep token in backend API route
const AGENTVERSE_TOKEN = 'bearer-token'; // Only server-side
  1. Define configuration as constants at the top
  2. Keep tokens server-side only
  3. Reuse client instances across requests
  4. Handle errors gracefully
  5. Set appropriate timeouts

Conclusion

The uAgent Client library represents a significant step forward in making Fetch.ai's uAgents accessible to JavaScript and TypeScript developers. By handling all the complexity of protocol communication, bridge management, and Agentverse integration, it allows developers to focus on building their applications rather than wrestling with low-level integration details.

The integration with Agentverse connects your applications to the broader Fetch.ai ecosystem. Your bridge agents become discoverable, can communicate with other agents, and can participate in distributed AI systems.

Additional Resources