Construyendo un agente personal de IA en un par de horas

Me ha sorprendido mucho lo rápido que ahora los constructores individuales pueden enviar prototipos reales y útiles.

Herramientas como Claude Code, Google AntiGravity y el creciente ecosistema que las rodea han cruzado un umbral: puedes inspeccionar lo que otros están construyendo en línea y darte cuenta de qué tan rápido puedes construir tú hoy.

Durante las últimas semanas, comencé a reservar una o dos horas al día exclusivamente para construir con mi pila de IA:

Google AntiGravity Modelos de Google Gemini Pro Claude a los que se accede a través de AntiGravity

Esta configuración ha cambiado fundamentalmente mi forma de pensar sobre la creación de prototipos, la velocidad de iteración y lo que un "agente personal de IA" puede hacer de manera realista hoy en día. Más importante aún, me hizo volver a dedicarme a la codificación y la construcción, algo que personalmente había sacrificado una vez que mi función en DareData cambió hacia la gestión y la orquestación en lugar de la ejecución.

Individualmente, esta revolución ha sido una bendición para alguien que siempre iba a decantarse por roles gerenciales. Elimina la compensación que había aceptado: que hacer crecer una empresa significaba abandonar la construcción por completo. Ya no tengo que elegir entre construir y gestionar, de hecho se refuerzan mutuamente.

Pero aquí hay una implicación más amplia para las personas que “recién” se están desarrollando. Si los agentes de IA se encargan cada vez más de la ejecución, entonces la pura implementación dejará de ser suficiente. Los desarrolladores se verán empujados (lo quieran o no) hacia la coordinación, la toma de decisiones y… la gestión, algo que los contribuyentes individuales odian de memoria. En otras palabras, las habilidades de gestión pasan a formar parte del conjunto técnico y los agentes de IA son parte del contexto que se gestiona.

Lo que más me sorprendió es lo transferibles que resultaron ser mis habilidades de gestión existentes:

Guiar al agente en lugar de microgestionarlo Solicitar resultados en lugar de instrucciones Mapear, priorizar y señalar las áreas grises

En la práctica, estoy gestionando y coordinando a un empleado virtual. Puedo influir profundamente en algunas partes de su trabajo sin dejar de ignorar casi por completo otras, y eso no es un error, es una característica importante. En mi asistente personal de IA, por ejemplo, puedo razonar claramente sobre el backend, pero no tengo ni idea sobre el frontend. El sistema sigue funcionando, porque mi función ya no es saberlo todo, sino dirigir el sistema en la dirección correcta.

Esto es directamente análogo a cómo coordino a las personas dentro de la empresa. A medida que DareData crece, no contratamos réplicas de los fundadores. Contratamos intencionalmente personas que pueden hacer cosas que nosotros no podemos hacer y, con el tiempo, cosas que nunca aprenderemos lo suficientemente profundamente como para hacerlas bien.

Pila de construcción actual: Google AntiGravity – Imagen del autor

Basta de autorreflexión sobre la gestión. Veamos lo que estoy construyendo porque para eso estás aquí:

Un asistente personal de IA diseñado en torno a mis rutinas reales, no una plantilla de productividad genérica. Se adapta a mi forma de trabajar, pensar y tomar decisiones. Una aplicación móvil que recomienda un álbum de música por semana, sin el sistema de recomendación tradicional. No hay refuerzo en la zona de confort y eso me ayuda a ampliar mis zonas de escucha. Un juego para dispositivos móviles creado en torno a un solo personaje que avanza a través de mazmorras en capas, desarrollado principalmente como un patio de juegos creativo más que como un producto comercial.

Lo interesante es que, si bien me siento cómodo codificando la mayor parte del backend, el desarrollo front-end no es una habilidad que tenga, y si me viera obligado a hacerlo yo mismo, estos proyectos se ralentizarían de horas a días, o simplemente nunca se enviarían.

Esa restricción ahora es en gran medida irrelevante. Con esta nueva pila, la imaginación se convierte en el verdadero cuello de botella. El costo de “no saber” una capa entera se ha derrumbado.

Entonces, en el resto de esta publicación, analizaré mi asistente personal de IA: qué hace, cómo está estructurado y por qué funciona para mí. Mi objetivo es abrirlo una vez que se estabilice, para que otros puedan adaptarlo a sus propios flujos de trabajo. Actualmente es muy específico de mi vida, pero esa especificidad es intencional y hacerlo más general es parte del experimento.

Conoce a Fernão

Fernão Lopes fue un cronista de la monarquía portuguesa. Elegí deliberadamente una figura histórica portuguesa: los portugueses tienen la costumbre de asignar nombres históricos a casi cualquier cosa. Si eso suena estereotipadamente portugués, es intencional.

Fernão es portugués pero en realidad habla inglés, llámelo un cronista moderno del siglo XXI.

Fernão Lopes, cronista del reino portugués – Fuente de la imagen: Fundación Wikimedia

En este punto, estoy haciendo dos cosas que normalmente evito: antropomorfizar la IA y apoyarme en un instinto de denominación muy portugués. Considérelo una señal inofensiva de que estoy envejeciendo.

Aparte de eso, ¿qué hace realmente Fernão por mí? El mejor lugar para empezar es su portada.

Portada de Fernão – Imagen del autor

Fernão es un tipo atractivo que actualmente desempeña cinco tareas:

Horario del día: planifica mi día reuniendo calendarios, tareas pendientes y objetivos, y luego convirtiéndolos en algo que pueda seguir. Asistente de redacción: me ayuda a revisar y limpiar borradores de publicaciones de blogs y otros textos. Portfolio Helper: sugiere empresas o ETF para agregar en función de las necesidades de reequilibrio y de lo que está sucediendo en el mundo macro (sin pretender ser una bola de cristal). Organizador financiero: extrae los gastos de mis extractos bancarios y los carga todo en la aplicación Cashew, lo que me ahorra otra tarea que me llevaba entre 3 y 4 horas al mes. Suscripciones y descuentos: realiza un seguimiento de todas mis suscripciones y muestra descuentos o beneficios que probablemente tengo pero que nunca recuerdo usar.

En esta publicación, me centraré en la aplicación Programación diaria.

Por el momento, el Horario del Día de Fernão hace tres cosas simples:

Recupera mi calendario, incluidas todas las reuniones programadas. Extrae mis tareas pendientes de Microsoft To Do. Recupera mis resultados clave personales de Notion.

Todo esto está conectado a través de API. La idea es sencilla: todos los días, Fernão analiza mis limitaciones, prioridades y compromisos y luego genera el mejor cronograma posible para mí.

Los poderes actuales de Fernão – Imagen del autor

Generar un cronograma en el front-end es bastante fácil (todo el front-end estaba codificado por vibración). Aquí está el botón generar programación:

Generar horario para un día específico – Imagen del autor

Una vez que presiono Generar programación, Fernão comienza a cocinar en segundo plano:

Fernão está generando un cronograma – Imagen del autor

Los pasos son entonces, en orden: recuperar mi calendario, tareas y datos de Notion.

El siguiente punto es también donde la alfabetización básica en codificación realmente comienza a importar, no porque todo el siguiente código no funcione, sino porque es necesario comprender qué está sucediendo y dónde las cosas pueden eventualmente fallar o necesitar mejoras.

Comencemos con la búsqueda del calendario. Por el momento, esto se gestiona mediante una única y gigantesca función creada por Claude que no está completamente optimizada.

def get_events_for_date(target_date=None): """ Obtiene eventos para una fecha específica de Google Calendar a través de feeds ICS. Args: target_date: objeto datetime.date para el día objetivo. Si no hay ninguno, usa hoy. Devuelve una lista de diccionarios de eventos. """ # URL de calendario codificadas (no se usa env var para evitar problemas con los marcadores de posición) CALENDAR_URLS = [ 'cal1url', 'call2url' ] LOCAL_TZ = os.getenv('TIMEZONE', 'Europe/Lisbon') # Obtener zona horaria local = tz.gettz(LOCAL_TZ) # Si no se proporciona una fecha objetivo, use hoy si la fecha objetivo es Ninguna: target_date = datetime.now(local).date() # Crear fecha y hora para los límites del día objetivo day_start = datetime.combine(target_date, datetime.min.time()).replace(tzinfo=local) day_end = day_start + timedelta(days=1) # Depurar: Imprime el rango de fechas que estamos comprobando print(f"n[Debug] Comprobando calendarios para la fecha: {target_date.strftime('%Y-%m-%d')}") print(f" Inicio: {day_start.strftime('%Y-%m-%d %H:%M %Z')}") print(f" Fin: {day_end.strftime('%Y-%m-%d %H:%M %Z')}") print(f" Zona horaria: {LOCAL_TZ}") all_events =[]# Obtener de cada calendario para idx, cal_url en enumerate(CALENDAR_URLS, 1): calendar_name = f"Calendar {idx}" print(f"n[Debug] Obteniendo {calendar_name}…") intenta: # Cargar el calendario desde la URL de ICS con el tiempo de espera adecuado r = request.get(cal_url, timeout=30) r.raise_for_status() cal = Calendar(r.text) events_found_this_cal = 0 total_events_in_cal = len(list(cal.events)) print(f" Total de eventos en {calendar_name}: {total_events_in_cal}") # Usar la línea de tiempo para filtrar eficientemente eventos para el rango de fechas del día objetivo # Convertir horas locales a UTC para filtrar la línea de tiempo day_start_utc = day_start.astimezone(timezone.utc) day_end_utc = day_end.astimezone(timezone.utc) # Obtener eventos en el rango del día objetivo usando la línea de tiempo days_timeline = cal.timeline.overlapping(day_start_utc, day_end_utc) para e en days_timeline: si no e.begin: continuar # Obtener la hora de inicio del evento start = e.begin.datetime si start.tzinfo es Ninguno: start = start.replace(tzinfo=timezone.utc) # Convertir a la zona horaria local start_local = start.astimezone(local) # Depurar: Imprime los primeros eventos para ver las fechas si events_found_this_cal < 3: print(f" Evento: '{e.name}' at {start_local.strftime('%Y-%m-%d %H:%M')}") # Obtener la hora de finalización end = e.end.datetime if e.end else Ninguno end_local = end.astimezone(local) if end else Ninguno all_events.append({ "title": e.name, "start": start_local.strftime("%H:%M"), "end": end_local.strftime("%H:%M") if end_local else Ninguno, "location": e.location o "", "description": e.description o "" }) events_found_this_cal += 1 print(f" [OK] Se encontraron {events_found_this_cal} evento(s) para el día objetivo en {calendar_name}") excepto request.exceptions.RequestException como e: print(f" [X] Error de red al obtener {calendar_name}: {str(e)}") continuar excepto Excepción como e: print(f" [X] Error al procesar {calendar_name}: {type(e).__name__}: {str(e)}") continuar # Ordenar por hora de inicio all_events.sort(key=lambda x: x["start"]) # Imprimir todos los eventos en detalle if all_events: print(f"n[Google Calendar] Se encontraron {len(all_events)} evento(s) para {target_date.strftime('%Y-%m-%d')}:") print("-" * 60) for event in all_events: time_str = f"{event['start']}-{event['end']}" if event['end'] else evento['inicio'] ubicación_str = f" @ {evento['ubicación']}" if evento['ubicación'] else "" print(f" {time_str} | {event['title']}{ubicación_str}") print("-" * 60) else: print(f"n[Google Calendar] No hay eventos para {target_date.strftime('%Y-%m-%d')}") return all_events

Como desarrollador de Python, todas las declaraciones impresas me molestan. Pero ese es un problema para la siguiente fase de Fernão: refactorizar y optimizar el código una vez que la lógica del producto sea sólida.

Aquí también es donde realmente veo funcionar la dinámica humano + IA. Puedo identificar inmediatamente varias formas de mejorar esta función (reducir la verbosidad, reducir la latencia innecesaria, limpiar el flujo), pero hacerlo bien aún requiere tiempo, juicio e intención. La IA me ayuda a moverme rápido; no reemplaza la necesidad de saber qué aspecto tiene lo extraordinario.

Por ahora, no he dedicado mucho tiempo a optimizarlo y es una elección consciente. A pesar de sus asperezas, la función hace exactamente lo que necesita hacer: extrae datos de mis calendarios y envía la información de la reunión a Fernão, habilitando todo lo que viene a continuación.

A continuación, Fernão saca mis tareas de Microsoft To Do. Aquí es donde viven mis tareas diarias (las cosas pequeñas y concretas que hay que hacer y que dan estructura a un día específico). Todo esto se configura directamente en la aplicación Microsoft To Do, que es una parte fundamental de mi flujo de trabajo diario.

Si tiene curiosidad sobre el sistema de productividad más amplio detrás de esto, escribí sobre ello en una publicación relacionada en el hermano de este blog (Wait a Day) vinculada a continuación.

Entonces, veamos otra función detallada:

def get_tasks(target_date=None): """ Obtiene tareas de Microsoft To Do para una fecha específica (tareas que vencen en esa fecha o antes). Args: target_date: objeto datetime.date para el día objetivo. Si no hay ninguno, usa hoy. Devuelve una lista de diccionarios de tareas. """ CLIENT_ID = os.getenv('MS_CLIENT_ID', 'CLIENT_ID_KEY') AUTHORITY = "https://login.microsoftonline.com/consumers" SCOPES = ['Tasks.ReadWrite', 'User.Read'] # Configurar caché de token persistente = SerializableTokenCache() cache_file = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), '.token_cache.bin') si os.path.exists(cache_file): con open(cache_file, 'r') como f: cache.deserialize(f.read()) # Autenticación con aplicación de caché persistente = PublicClientApplication(CLIENT_ID, autoridad=AUTHORITY, token_cache=cache) cuentas = app.get_accounts() resultado = Ninguno si cuentas: resultado = app.acquire_token_silent(SCOPES, cuenta=cuentas[0]) si no es el resultado o "access_token" no es el resultado: para la cuenta en cuentas: app.remove_account(cuenta) resultado = Ninguno si no es el resultado: flow = app.initiate_device_flow(scopes=SCOPES) si "user_code" no está en el flujo: print(f"[MS To Do] No se pudo crear el flujo del dispositivo: {flow.get('error_description', 'Unknown error')}") return[]si "mensaje" en el flujo: print(flow['message']) resultado = app.acquire_token_by_device_flow(flow) si no es el resultado o "access_token" no está en el resultado: print(f"[MS To Do] Error de autenticación: {result.get('error_description', 'No access token') if result else 'No result'}") return[]headers = {"Autorización": f"Bearer {resultado['access_token']}"} # Obtener límites de fecha para la fecha objetivo # Si no se proporciona una fecha objetivo, use hoy si la fecha objetivo es Ninguna: desde fecha y hora fecha de importación target_date = date.today() # Convertir fecha a fecha y hora en UTC para comparar ahora = datetime.now(timezone.utc) target_day_end = datetime.combine(target_date, datetime.max.time()).replace(tzinfo=timezone.utc) # Obtener todas las listas listas_r = request.get("https://graph.microsoft.com/v1.0/me/todo/lists", headers=headers) if listas_r.status_code!= 200: devolver[]listas_res = listas_r.json().get("valor",[]) todas_tareas =[]# Obtener tareas de todas las listas con filtrado del lado del servidor para task_list en listas_res: list_id = task_list["id"] list_name = task_list["displayName"] # Filtro simple: solo obtenga tareas incompletas params = {"$filter": "status ne 'completed'"} task_r = request.get( f"https://graph.microsoft.com/v1.0/me/todo/lists/{list_id}/tasks", headers=headers, params=params ) si tareas_r.status_code != 200: continuar tareas = tareas_r.json().get("valor",[]) # Filtrar y transformar tareas para tarea en tareas: due_date_obj = task.get("dueDateTime") si no due_date_obj: continuar due_date_str = due_date_obj.get("dateTime") si no due_date_str: continuar intentar: due_date = datetime.fromisoformat(due_date_str.split('.')[0]) si due_date.tzinfo es Ninguno: due_date = due_date.replace(tzinfo=timezone.utc) # Incluir todas las tareas que vencen en o antes de la fecha objetivo si due_date <= target_day_end: # Determinar el estado según la fecha objetivo target_day_start = datetime.combine(target_date, datetime.min.time()).replace(tzinfo=timezone.utc) if due_date < target_day_start: status = "VENCIDO" elif fecha_de_vencimiento <= fin_día_objetivo: estado = f"VENCIMIENTO {fecha_objetivo.strftime('%Y-%m-%d')}" else: estado = "FUTURO" all_tasks.append({ "lista": nombre_lista, "título": tarea["título"], "vencimiento": fecha_debido.strftime("%Y-%m-%d"), "importancia": task.get("importance", "normal"), "status": status }) excepto Excepción como e: continuar # Imprimir resumen de tareas si all_tasks: print(f"[MS To Do] {len(all_tasks)} tarea(s) para {target_date.strftime('%Y-%m-%d')} o vencidas") else: print(f"[MS To Do] No hay tareas pendientes el {target_date.strftime('%Y-%m-%d')} or overdue") # Guardar caché de token para la próxima ejecución si cache.has_state_changed: con open(cache_file, 'w') as f: f.write(cache.serialize()) return all_tasks

Esta función recupera una lista completa de mis tareas del día actual (y las atrasadas de días anteriores); aquí hay un ejemplo de cómo se ven en tareas pendientes:

Ejemplo de tareas en la aplicación To-Do – Imagen del autor

Después de seleccionar tareas de Tareas pendientes, también quiero que Fernão comprenda hacia dónde intento llegar, no solo lo que hay en la lista de hoy. Para eso, recupera mis objetivos directamente desde una página de Notion donde tengo los resultados clave de mi año.

A continuación se muestra un ejemplo de cómo se estructuran esos objetivos:

la primera columna muestra mi punto de referencia al comienzo del año, la última columna define el objetivo que quiero alcanzar y la columna de la derecha sigue mi progreso actual.

El siguiente ejemplo incluye cuántas publicaciones de blog quiero escribir para ustedes este año, así como la cantidad total de libros que pretendo vender en mis tres títulos.

Esto le da a Fernão un contexto más amplio sobre qué priorizar en las tareas, como verá en el mensaje para crear el cronograma.

Ejemplo de objetivos personales: imagen del autor

Por cierto, mientras escribía esta publicación, terminé agregando un pequeño widget a la aplicación. Si estamos construyendo un asistente personal, también podría tener algo de personalidad.

Entonces le pregunté a Géminis:

"¿Puedes agregar una animación divertida mientras la aplicación recupera eventos del calendario, verifica tareas pendientes y extrae datos de Notion? Tal vez un pequeño widget de Fernão revolviendo una olla, con la leyenda 'Fernão está cocinando'".

Fernão está cocinando – Imagen del autor

Una vez que finaliza esta ronda, las tareas y los eventos del calendario se recopilan con éxito y se muestran en la interfaz de Fernão (a continuación se muestra una muestra de las tareas y reuniones de mi día).

Tareas y eventos del calendario obtenidos por Fernao – Imagen del autor

Y ahora la parte divertida: con calendarios, tareas y objetivos en mano, Fernão compone todo mi día en un único y mágico plan:

07:30-09:30 | Gimnasio 09:30-09:40 | Verifique las hojas de tiempo en Odoo (Fecha de vencimiento: 2026-02-04) 09:40-09:55 | Revisar tareas en Tareas pendientes – [Tarea de organización] (Fecha: 2026-02-04) 09:55-10:15 | Lea Feedly Stuff – [Actualización de noticias] (Fecha de vencimiento: 2026-02-04) 10:15-10:30 | Escriba un documento sobre cultura, inspiración: https://pt.slideshare.net/slideshow/culture-1798664/1798664 (Fecha de vencimiento: 2026-02-04) 10:30-10:45 | Responder LinkedIns – [Tarea de organización] (Fecha: 2026-02-04) 10:45-11:00 | Check Looker (Fecha límite: 2026-02-04) 11:00-11:30 | Esta semana en AI Post (fecha de vencimiento: 2026-02-04) 11:30-12:00 | Preparar Podcast Decodificación AI 12:00-13:00 | Podcast Decodificando IA – Ivo Bernardo, DareData (Evento) 13:00-14:00 | Pausa para el almuerzo 14:00-14:30 | Candidato 1 (nombre oculto) e Ivo Bernardo @ Google Meet (Evento) 14:30-18:00 | Preparar DareData Estado de la Unión 18:00-18:30 | Candidato 2 (nombre oculto) e Ivo Bernardo @ Google Meet (Evento) 18:30-19:00 | Candidato 3 (nombre oculto) e Ivo Bernardo @ Google Meet (Evento) 19:00-19:30 | Candidato 4 (nombre oculto) e Ivo Bernardo @ Google Meet (Evento) 19:30-20:00 | Candidato 5 (nombre oculto) e Ivo Bernardo @ Google Meet (Evento) 20:00-20:15 | Consulte las señales de uso de información privilegiada para obtener ideas sobre acciones https://finviz.com/insidertrading?tc=1 (Atrasado) 20:15-20:30 | Cronograma de marketing (atrasado) 20:30-21:00 | Pausa para cenar 21:00-22:00 | Ler 22:00-22:15 | Cierre del día: revisión y preparación para mañana

Este es uno de esos momentos que realmente se siente un poco mágico. No porque la tecnología sea opaca, sino porque el resultado es muy limpio. Una mezcla desordenada de reuniones, tareas y objetivos a largo plazo se convierte en un día que realmente puedo ejecutar.

Lo que lo hace aún más interesante es lo sencillo que es el paso final. Después de realizar todo el trabajo pesado en segundo plano (eventos del calendario, tareas pendientes, objetivos), no organizo un proceso complejo ni una cadena de indicaciones. Utilizo un solo mensaje.

Ese mensaje toma todo lo que Fernão sabe sobre mis limitaciones y prioridades y lo convierte en el día que estás a punto de ver.

nombre: daily_schedule descripción: Generar un cronograma diario basado en eventos y tareas del calendario modelo: gemini-2.5-flash-lite temperatura: 0.3 max_tokens: 8192 variables: – contexto_fecha – cadena_eventos – cadena_tareas – contexto – todo_context – auto_context – actualmente_lectura – notion_context – is_today plantilla: | Eres mi asistente personal de programación de IA. ¡Ayúdame a planificar mi día! **FECHA OBJETIVO:** Planificación para {date_context} **EVENTOS (Fijo):** {events_str} **TAREAS A PROGRAMAR:** {tasks_str} **MI CONTEXTO:** {context} **CONTEXTO DE LA TAREA (cuánto tiempo suelen tardar las tareas):** {todo_context} **CONTEXTO DE APRENDIZAJE AUTOMÁTICO:** {auto_context} **LECTURA ACTUAL:** {currently_reading} **RESULTADOS Y OBJETIVOS (de Notion):** {notion_context} **REGLAS DE HORARIO:** 1. **No se pueden programar tareas durante los eventos del calendario** – los eventos son fijos 2. **Descansos obligatorios:** – Almuerzo: 12:30-13:30 (reservar cuando sea posible) – Cena: 20:30-21:00 – Jugar con mi gato: 45-60 minutos repartidos en algún lugar del día 3. **Ajuste de tareas:** Ajuste inteligentemente las tareas entre eventos según el tiempo disponible 4. **Estimaciones de tiempo:** Utilice el contexto de la tarea para estimar cuánto tiempo tomará cada tarea 5. **Horas de trabajo:** 09:30 a 22:00 6. **Inicie el cronograma:** {is_today} **SU TRABAJO:** 1. Cree un cronograma por horas completo para {date_context} 2. Ajuste todas las tareas entre eventos y descansos 3. **Priorice las tareas según en mis Resultados y Objetivos de Notion** – céntrese en lo que más importa 4. Sea conversador – si necesita más información sobre una tarea, ¡pregúnteme! 5. **Guarde lo aprendido:** Si le doy contexto sobre las tareas, reconózcalo y diga que lo recordará **FORMATO:** Comience con un saludo amistoso, luego proporcione el horario en este formato: “` 09:30-10:00 | Tarea/Evento 10:00-11:00 | Tarea/Evento… “` Después del cronograma, pregunte si necesito algún ajuste o si necesita aclaración sobre alguna tarea. Genera la agenda de mi día ahora, ¡gracias!

Y con esto, Fernão definitivamente está cocinando:

Fernão vuelve a cocinar – Imagen del autor

Ha sido un sistema realmente divertido de construir. Seguiré evolucionando a Fernão, dándole nuevas responsabilidades, rompiendo cosas, arreglándolas y compartiendo lo que aprendo en el camino hasta aquí.

Con el tiempo, también planeo escribir tutoriales prácticos sobre cómo crear e implementar aplicaciones similares usted mismo. Por ahora, Fernão vive sólo en mi máquina, y es probable que siga siendo así. Aún así, tengo la intención de abrirlo. No porque sea universalmente útil en su forma actual (está profundamente adaptado a mi vida), sino porque las ideas subyacentes podrían serlo.

Para que eso sea posible, necesitaré abstraer herramientas, modularizar la funcionalidad y permitir que las funciones se activen y desactiven para que otros puedan configurar el asistente según sus propios flujos de trabajo, en lugar del mío.

Podría haber construido algo similar usando solo Claude Code. No lo hice. Quería control total: la libertad de intercambiar modelos, combinar proveedores y, eventualmente, ejecutar Fernão en un LLM local en lugar de depender de API externas. Aquí la propiedad y la flexibilidad me importan más que la comodidad.

Si estuvieras creando un asistente personal de IA, ¿qué tareas le asignarías? Realmente me gustaría escuchar tus ideas e intentar construirlas dentro de Fernão. Deje un comentario ya que este proyecto aún está evolucionando y las perspectivas externas suelen ser la forma más rápida de mejorarlo.