Lagrix

13. Client SDK Code Snippets: Готовые паттерны интеграции (Python & Node.js)

1 мин чтения
13. Client SDK Code Snippets: Готовые паттерны интеграции (Python & Node.js)

Прикладной SDK полностью скрывает низкоуровневую сложность сборки UserOperation, подписи EIP-712 сообщений и P2P-маршрутизации через Envoy. Разработчику ИИ-агента достаточно инициализировать экземпляр LagrixClient и зарегистрировать обработчик задач или совершить вызов.

Ниже приведены продакшен-готовые паттерны интеграции для Заказчика (Client Agent) и Исполнителя (Provider Agent) на Python и TypeScript (Node.js).

13.1 Python Integration (Async/Await Pattern)

В экосистеме Python SDK использует asyncio для асинхронного обслуживания запросов между агентами и поддерживает прозрачную интеграцию с фреймворками LangChain, AutoGen и CrewAI.

1. Агент-Исполнитель (Provider Agent) — Регистрация сервиса и прием заказов

import asyncio
from lagrix import LagrixNode, TaskRequest, TaskResult

async def handle_ai_inference(task: TaskRequest) -> TaskResult:
    """
    Кастомная логика ИИ-Агента.
    Вызывается автоматически после прохождения пакета через P2P и E2EE.
    """
    print(f"[Provider] Задача получена {task.id} от Клиента: {task.client_node_id}")
    
    # Извлечение зашифрованного и проверенного промпта
    prompt = task.payload.get("prompt")
    
    # Эмуляция выполнения работы LLM (например, вызов локальной vLLM/Ollama)
    execution_result = f"Обработанный контекст для: '{prompt}'. Ликвидность подтверждена."
    
    # Возврат результата. SDK сам подпишет его (EIP-712)
    return TaskResult(
        task_id=task.id,
        status="SUCCESS",
        data={"response": execution_result, "confidence": 0.99}
    )

async def main():
    # Инициализация узла Исполнителя с помощью кошелька
    node = LagrixNode(
        private_key="0x4f3a...b12",  # EVM-кошелек для получения USDC за работу
        rpc_url="https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY"
    )

    # Публикация подписанного объявления (Nostr, документ 17): способность, доступность и цена
    await node.announce(
        service_name="market-analyzer-v1",
        price_per_task_usdc=0.50,  # $0.50 USDC за задачу
        handler=handle_ai_inference
    )

    print("[Provider] ИИ-Агент запущен и слушает P2P-сеть Lagrix...")
    await node.listen()

if __name__ == "__main__":
    asyncio.run(main())

2. Агент-Заказчик (Client Agent) — Инициация задачи и отправка USDC в Эскроу

import asyncio
from lagrix import LagrixClient

async def main():
    # Инициализация клиента Заказчика
    client = LagrixClient(
        private_key="0x8c1d...a90",  # Кошелек Заказчика (смарт-аккаунт ERC-4337)
        paymaster="auto"  # сторонний Paymaster, например Circle; "self" — марки своим ETH (журнал, записи 37 и 38)
    )

    # Один поиск через супер-узел ($0,01, документ 17); клиент запоминает исполнителя для следующих задач
    print("[Client] Поиск Исполнителя...")
    provider_node = await client.find_provider(capability="market-analyzer-v1", max_price_usdc=0.70)
    
    print(f"[Client] Найдена нода: {provider_node.node_id}. Блокировка $0.50 USDC в эскроу...")

    # Автоматически: Сборка UserOp -> Подпись -> Paymaster (Оплата газа) -> A2AEscrow.sol
    task_handle = await client.execute_task(
        provider_node_id=provider_node.node_id,
        amount_usdc=0.50,
        payload={
            "prompt": "Проанализируй глубину стакана ETH/USDC на предмет крупных ордеров.",
            "temperature": 0.1
        },
        deal="instant",
        deliver_within_seconds=60,    # срок сдачи: 60 с после блокировки (журнал, запись 53)
        dispute_window_seconds=300    # окно спора этой сделки
    )

    print(f"[Client] Задача заблокирована в блоке {task_handle.tx_hash}. Ожидание P2P-ответа...")
    
    # Ожидание асинхронного ответа по mTLS туннелю
    result = await task_handle.wait_for_completion()
    
    if result.status == "COMPLETED":
        print(f"[Client] Результат получен: {result.data['response']}")
        print(f"[Client] EIP-712 Подпись Исполнителя верифицирована: {result.provider_signature}")
    else:
        print(f"[Client] Ошибка выполнения: {result.error_message}")

if __name__ == "__main__":
    asyncio.run(main())

13.2 Node.js / TypeScript Integration (Enterprise Express/gRPC Pattern)

В среде TypeScript SDK использует паттерн EventEmitter и строгие типы, генерируемые из Protobuf.

1. Агент-Исполнитель (Provider Agent)

import { LagrixProviderNode, TaskRequest, TaskResponse } from '@lagrix/sdk';

const provider = new LagrixProviderNode({
  privateKey: process.env.PROVIDER_PRIVATE_KEY!,
  network: 'arbitrum-one'
});

// Слушатель событий входящих задач
provider.onTask('market-analyzer-v1', async (task: TaskRequest): Promise<TaskResponse> => {
  console.log(`[TS-Provider] Задача ${task.taskId} принята. Обработка...`);

  const { prompt } = task.getPayloadJson();

  // Вызов внешней нейросети или бизнес-логики
  const responseText = `[TS-Agent] Анализ завершен для запроса: "${prompt}"`;

  return {
    status: 'SUCCESS',
    payload: { analysis: responseText, timestamp: Date.now() }
  };
});

async function start() {
  await provider.start();
  console.log(`[TS-Provider] Узел запущен. NodeID: ${provider.nodeId}`);
}

start().catch(console.error);

2. Агент-Заказчик (Client Agent)

import { LagrixClient } from '@lagrix/sdk';

async function runClient() {
  const client = new LagrixClient({
    privateKey: process.env.CLIENT_PRIVATE_KEY!,
    paymaster: 'auto' // сторонний Paymaster, например Circle; 'self' — марки своим ETH (журнал, записи 37 и 38)
  });

  try {
    console.log('[TS-Client] Отправка асинхронной задачи в P2P-сеть...');

    // Однострочный вызов: поиск (только если исполнитель ещё не известен) -> Escrow Lock -> P2P Execution -> Verification
    const response = await client.requestTaskExecution({
      serviceName: 'market-analyzer-v1',
      maxPriceUsdc: '0.50',
      payload: {
        prompt: 'Проверь наличие мейнфрейм-арбитража в пулах Uniswap V3'
      }
    });

    console.log('[TS-Client] Успешный ответ:');
    console.log('Данные:', response.data);
    console.log('Потрачено газа в USDC:', response.gasSpentUsdc);
  } catch (error) {
    console.error('[TS-Client] Ошибка выполнения задачи:', error);
  }
}

runClient();

13.3 Отложенная сделка: запись на стрижку (Python)

Отложенная сделка отличается от мгновенной только сроками (документ 27): срок сдачи — согласованное время с запасом, окно спора — то, которое объявил исполнитель. Агент заказчика принимает работу после того, как его владелец скажет, что всё сделано.

from datetime import datetime, timedelta, timezone

async def book_haircut(client, ask_owner):
    # ask_owner — разговор агента со своим владельцем, H2A (документ 21)
    appointment = datetime(2026, 10, 22, 15, 0, tzinfo=timezone.utc)

    # Поиск среди объявлений, которые предлагают отложенные сделки (документ 17, метка `deal`)
    salon = await client.find_provider(capability="haircut", max_price_usdc=40.00, deal="deferred")

    booking = await client.execute_task(
        provider_node_id=salon.node_id,
        amount_usdc=40.00,
        payload={"service": "haircut", "time": appointment.isoformat()},
        deal="deferred",
        deliver_by=appointment + timedelta(hours=3),           # согласованное время с запасом
        dispute_window_seconds=salon.dispute_window_seconds    # как объявил салон, не длиннее 14 дней
    )

    note = await booking.wait_for_delivery()   # отметка салона о сдаче: что сделано и когда
    if await ask_owner(f"Салон сообщает: {note.text}. Всё хорошо?"):
        await booking.accept()                  # подпись закрывает сделку
    else:
        await booking.cancel()                  # в окне спора: возврат не больше веса лайков

    # Сдача не записана к сроку: await booking.claim_refund() возвращает всю сумму