Saltar al contenido principal

Descripción general

Esta página es la versión en Laravel del tutorial oficial de bots de AT Protocol. Explica cómo implementar en PHP/Laravel, mediante el paquete laravel-bluesky, un contenido pensado originalmente para TypeScript. En el tutorial oficial se descargan los archivos Lexicon en cada ocasión con el comando lex, pero laravel-bluesky ya incorpora previamente todos los Lexicon desde atproto-lexicon-contracts, así que ese paso no es necesario. Usando los comandos de Artisan y los métodos del trait HasShortHand, puedes realizar prácticamente todas las operaciones.

Requisitos previos

  • Tener instalado el paquete laravel-bluesky
  • Disponer de una cuenta de Bluesky y una app password
Consulta el método de instalación en Laravel Bluesky.
BLUESKY_IDENTIFIER=yourbot.bsky.social
BLUESKY_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx

Parte 1: bot básico (publicación)

Crear un comando Artisan

Crea el comando para el bot con php artisan make:command.
php artisan make:command BotPostCommand
Edita el app/Console/Commands/BotPostCommand.php generado.
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Revolution\Bluesky\Facades\Bluesky;

class BotPostCommand extends Command
{
    protected $signature = 'bot:post';

    protected $description = 'Post to Bluesky';

    public function handle(): void
    {
        Bluesky::login(
            identifier: config('bluesky.identifier'),
            password: config('bluesky.password'),
        )->post('🙂');

        $this->info('Posted successfully.');
    }
}

Ejecución manual

php artisan bot:post

Ejecución automática con programación de tareas

Añade la configuración de ejecución periódica en routes/console.php.
use Illuminate\Support\Facades\Schedule;

// Publica cada tres horas
Schedule::command('bot:post')->everyThreeHours();
Para activar el scheduler, configura lo siguiente en cron.
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

Ejecución automática con GitHub Actions

Si no dispones de servidor, también puedes ejecutarlo automáticamente con GitHub Actions.
# .github/workflows/bot.yml
name: Bot Post

on:
  schedule:
    - cron: '0 */3 * * *'  # cada tres horas
  workflow_dispatch:

jobs:
  post:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.4'
      - run: composer install --no-dev --optimize-autoloader
      - run: php artisan bot:post
        env:
          BLUESKY_IDENTIFIER: ${{ secrets.BLUESKY_IDENTIFIER }}
          BLUESKY_APP_PASSWORD: ${{ secrets.BLUESKY_APP_PASSWORD }}
Registra BLUESKY_IDENTIFIER y BLUESKY_APP_PASSWORD como secrets de GitHub Actions.

Parte 2: bot de respuestas (monitorización de menciones)

Crearemos un bot que responde automáticamente a las menciones. También se incluye un ejemplo que usa IA para generar las respuestas.

Obtener notificaciones y responder a las menciones

php artisan make:command BotReplyCommand
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Record\Post;
use Revolution\Bluesky\Types\ReplyRef;
use Revolution\Bluesky\Types\StrongRef;

class BotReplyCommand extends Command
{
    protected $signature = 'bot:reply';

    protected $description = 'Reply to mentions on Bluesky';

    public function handle(): void
    {
        Bluesky::login(
            identifier: config('bluesky.identifier'),
            password: config('bluesky.password'),
        );

        $notifications = Bluesky::listNotifications(limit: 20)->json('notifications', []);

        foreach ($notifications as $notification) {
            // Procesa solo notificaciones de menciones
            if (data_get($notification, 'reason') !== 'mention') {
                continue;
            }

            // Omite las notificaciones ya leídas (las que tienen isRead a true ya se han procesado)
            if (data_get($notification, 'isRead')) {
                continue;
            }

            $uri = data_get($notification, 'uri');
            $cid = data_get($notification, 'cid');

            if (! $uri || ! $cid) {
                continue;
            }

            $ref = StrongRef::to(uri: $uri, cid: $cid);
            $reply = ReplyRef::to(root: $ref, parent: $ref);

            $post = Post::create('¡Hola! Gracias por la mención. 🙂')
                ->reply($reply);

            Bluesky::post($post);

            $this->info("Replied to: {$uri}");
        }

        // Marca las notificaciones como leídas
        Bluesky::updateSeenNotifications(now()->toISOString());
    }
}
Si la raíz del hilo es diferente, obtén la información del hilo con app.bsky.feed.getPostThread y configúralo en root. En la implementación simplificada se toma la publicación padre como raíz.

Programar el sondeo

// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::command('bot:reply')->everyFiveMinutes();

Generar respuestas usando IA

Combinando el paquete laravel/ai con el driver laravel-amazon-bedrock, puedes generar respuestas con IA según el contenido de la mención.
composer require laravel/ai revolution/laravel-amazon-bedrock
Crea el agente de IA.
<?php

namespace App\Ai\Agents;

use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Promptable;

class BotReplyAgent implements Agent
{
    use Promptable;

    public function instructions(): string
    {
        return 'Eres un bot amigable que opera en Bluesky. '
            . 'Genera una respuesta breve y cercana al mensaje del usuario. '
            . 'La respuesta debe tener 200 caracteres o menos.';
    }
}
Usa la respuesta de IA desde el comando.
<?php

namespace App\Console\Commands;

use App\Ai\Agents\BotReplyAgent;
use Illuminate\Console\Command;
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Record\Post;
use Revolution\Bluesky\Types\ReplyRef;
use Revolution\Bluesky\Types\StrongRef;

class BotReplyCommand extends Command
{
    protected $signature = 'bot:reply';

    protected $description = 'Reply to mentions on Bluesky using AI';

    public function handle(): void
    {
        Bluesky::login(
            identifier: config('bluesky.identifier'),
            password: config('bluesky.password'),
        );

        $notifications = Bluesky::listNotifications(limit: 20)->json('notifications', []);

        foreach ($notifications as $notification) {
            if (data_get($notification, 'reason') !== 'mention') {
                continue;
            }

            if (data_get($notification, 'isRead')) {
                continue;
            }

            $uri = data_get($notification, 'uri');
            $cid = data_get($notification, 'cid');
            $mentionText = data_get($notification, 'record.text', '');

            if (! $uri || ! $cid) {
                continue;
            }

            // Genera la respuesta con IA
            $replyText = (new BotReplyAgent)->prompt($mentionText)->text;

            $ref = StrongRef::to(uri: $uri, cid: $cid);
            $reply = ReplyRef::to(root: $ref, parent: $ref);

            $post = Post::create($replyText)->reply($reply);

            Bluesky::post($post);

            $this->info("AI replied to: {$uri}");
        }

        Bluesky::updateSeenNotifications(now()->toISOString());
    }
}
Consulta la configuración de laravel-amazon-bedrock en el driver de Amazon Bedrock.

Parte 3: bot de etiquetas

Es el equivalente al labelAsBot del tutorial oficial. Se aplica una self label al perfil de la cuenta del bot para indicar explícitamente que se trata de una cuenta automatizada.
El etiquetado se ejecuta una sola vez durante la configuración inicial. Se implementa como un comando aparte, independiente de los comandos de las partes 1 y 2.

Crear el comando del bot de etiquetas

php artisan make:command BotLabelCommand
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Record\Profile;
use Revolution\Bluesky\Types\SelfLabels;

class BotLabelCommand extends Command
{
    protected $signature = 'bot:label';

    protected $description = 'Add bot self-label to the Bluesky profile';

    public function handle(): void
    {
        Bluesky::login(
            identifier: config('bluesky.identifier'),
            password: config('bluesky.password'),
        )->upsertProfile(function (Profile $profile) {
            // Aplica la etiqueta !bot
            $profile->labels(SelfLabels::make(['!bot']));
        });

        $this->info('Bot label applied successfully.');
    }
}

Ejecutar

php artisan bot:label
Ejecuta este comando una sola vez durante la configuración inicial del bot. La etiqueta se guarda de forma permanente en el perfil.
!bot es una self label estándar de Bluesky. Se recomienda asignarla siempre en las cuentas de bots.

Sobre otros tutoriales oficiales

El tutorial oficial de AT Protocol incluye varios temas más. A continuación resumimos el estado de compatibilidad con laravel-bluesky.

Feed personalizado

En Feed Generator se explica en detalle cómo implementar un feed generator personalizado con Laravel.

Autenticación OAuth

En Socialite se explica cómo implementar la autenticación OAuth con Laravel Socialite. Es más sencilla que en el tutorial oficial.

Aplicación social (statusphere)

Está publicada una versión Laravel de statusphere en invokable/statusphere. Como se basa en un statusphere anterior que no usa los comandos lex ni tap, hay algunas diferencias respecto al tutorial oficial más reciente.

Enlaces de referencia

Última modificación el 13 de julio de 2026