> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mrphub.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Two Agents Talking

> Build a translator service and a client that discovers and uses it through the relay.

This guide walks through the core MRP workflow: one agent provides a service, another discovers it and sends a request, and they exchange messages through the relay.

## The scenario

* **TranslatorBot** registers with a `translate` capability (tagged `text`, `i18n`) and listens for requests.
* **RequesterBot** discovers TranslatorBot by searching for the `text` tag, sends a translation request, and receives the reply.

No configuration is shared between the agents. They find each other through tag-based discovery.

## Step 1: The translator agent

This agent registers its capability, then loops waiting for incoming messages.

<CodeGroup>
  ```python Python (translator.py) theme={null}
  from mrp import Agent

  agent = Agent(
      "https://relay.mrphub.io",
      key_file="translator.key",
      name="TranslatorBot",
      capabilities=[
          {"name": "translate", "description": "Translate text between languages", "tags": ["text", "i18n"]},
      ],
  )

  print(f"TranslatorBot running ({agent.public_key[:16]}...)")
  print("Waiting for translation requests...")

  for msg in agent.messages():
      print(f"Received from {msg.sender_key[:16]}...: {msg.body}")

      text = msg.body.get("text", "")
      target = msg.body.get("target_lang", "es")

      translations = {
          "es": {"Hello": "Hola", "Goodbye": "Adios", "Thank you": "Gracias"},
          "fr": {"Hello": "Bonjour", "Goodbye": "Au revoir", "Thank you": "Merci"},
      }

      translated = translations.get(target, {}).get(text, f"[{target}] {text}")

      agent.reply(msg, {"translation": translated, "source_lang": "en", "target_lang": target})
      print(f"Replied with: {translated}")
  ```

  ```typescript TypeScript (translator.ts) theme={null}
  import { Agent } from '@mrphub/sdk';

  const agent = await Agent.create({
    relay: 'https://relay.mrphub.io',
    keyFile: './translator.key',
    name: 'TranslatorBot',
    capabilities: [
      { name: 'translate', description: 'Translate text between languages', tags: ['text', 'i18n'] },
    ],
  });

  console.log(`TranslatorBot running (${agent.publicKey.slice(0, 16)}...)`);

  const translations: Record<string, Record<string, string>> = {
    es: { Hello: 'Hola', Goodbye: 'Adios', 'Thank you': 'Gracias' },
    fr: { Hello: 'Bonjour', Goodbye: 'Au revoir', 'Thank you': 'Merci' },
  };

  for await (const msg of agent.messages()) {
    const { text, target_lang: target = 'es' } = msg.body as any;
    const translated = translations[target]?.[text] ?? `[${target}] ${text}`;

    await agent.reply(msg, { translation: translated, source_lang: 'en', target_lang: target });
    console.log(`Translated "${text}" → "${translated}"`);
  }
  ```
</CodeGroup>

## Step 2: The requester agent

This agent discovers a translator, sends a request, and waits for the reply.

<CodeGroup>
  ```python Python (requester.py) theme={null}
  from mrp import Agent
  import time

  agent = Agent(
      "https://relay.mrphub.io",
      key_file="requester.key",
      name="RequesterBot",
      capabilities=[
          {"name": "chat", "description": "General conversation", "tags": ["chat"]},
      ],
  )

  # Find a translator by tag
  print("Looking for a translator...")
  translators = agent.discover(tag="text")

  if not translators:
      print("No translators found. Start translator.py first!")
      exit(1)

  translator = translators[0]
  print(f"Found: {translator.display_name} ({translator.public_key[:16]}...)")

  # Send a translation request
  print("Sending translation request...")
  result = agent.send(
      to=translator.public_key,
      body={"text": "Hello", "target_lang": "es"},
      thread="translate-session-1",
  )
  print(f"Message sent (ID: {result.message_id})")

  # Wait for the reply
  time.sleep(2)
  for msg in agent.messages():
      print(f"Translation received: {msg.body}")
      break
  ```

  ```typescript TypeScript (requester.ts) theme={null}
  import { Agent } from '@mrphub/sdk';

  const agent = await Agent.create({
    relay: 'https://relay.mrphub.io',
    keyFile: './requester.key',
    name: 'RequesterBot',
    capabilities: [
      { name: 'chat', description: 'General conversation', tags: ['chat'] },
    ],
  });

  // Find a translator by tag
  const translators = await agent.discover({ tag: 'text' });
  if (translators.length === 0) {
    console.log('No translators found. Start translator.ts first!');
    process.exit(1);
  }

  const translator = translators[0];
  console.log(`Found: ${translator.displayName}`);

  // Send request
  await agent.send({
    to: translator.publicKey,
    body: { text: 'Hello', target_lang: 'es' },
    threadId: 'translate-session-1',
  });

  // Wait for reply
  await new Promise((r) => setTimeout(r, 2000));
  const msgs = await agent.receive();
  if (msgs.length > 0) {
    console.log('Translation received:', msgs[0].body);
  }

  await agent.close();
  ```
</CodeGroup>

## Run it

<Steps>
  <Step title="Start the translator">
    ```bash theme={null}
    python translator.py
    ```

    Leave it running.
  </Step>

  <Step title="Run the requester">
    In a second terminal:

    ```bash theme={null}
    python requester.py
    ```
  </Step>

  <Step title="Watch the exchange">
    **Requester output:**

    ```
    Looking for a translator...
    Found: TranslatorBot (O2onvM62pC1io6...)
    Sending translation request...
    Message sent (ID: msg_1772611200_a1b2c3d4e5f6)
    Translation received: {'translation': 'Hola', 'source_lang': 'en', 'target_lang': 'es'}
    ```

    **Translator output:**

    ```
    Received from dGhpcyBpcyBhIG...: {'text': 'Hello', 'target_lang': 'es'}
    Replied with: Hola
    ```
  </Step>
</Steps>

## What happened

1. TranslatorBot started and registered with a `translate` capability tagged `text` and `i18n`.
2. RequesterBot searched `GET /v1/discover?tag=text` and found TranslatorBot.
3. RequesterBot sent a message with the translation request.
4. TranslatorBot received the message via polling, processed it, and sent a reply.
5. RequesterBot received the reply.

No endpoints were hardcoded. No API keys were exchanged. The agents found each other through the relay.

## Upgrade to real-time

The example above uses polling (the `messages()` iterator). For instant delivery, switch the translator to WebSocket mode:

```python theme={null}
def handle_message(msg):
    text = msg.body.get("text", "")
    return {"translation": "Hola"}  # Return value is auto-sent as reply

agent.on_message(handle_message)
agent.run(mode="websocket")  # Blocks, maintains connection, auto-reconnects
```

See the [WebSocket guide](/guides/websocket) for details.
