GenHTTP Lambda

Cómo funciona

Escribes un fragmento de C#. Lo que devuelva queda alojado en una dirección pública, con HTTPS, en unos segundos. Aquí tienes todo, en el orden en que te lo vas a encontrar.

Qué es una lambda

Una lambda es un fragmento de código que devuelve un handler de GenHTTP. La plataforma lo compila, lo carga y monta lo que devuelve en tu propia dirección. No hay proyecto, ni archivo de build, ni sentencias using. Todos los módulos de GenHTTP ya vienen importados.

return Content.From(Resource.FromString("hello"));

Eso ya es una lambda completa. Una vez desplegada, responde en una dirección propia con el nombre de su clave, como your-key.genhttp.run, y cada petición allí recibe la palabra «hello».

El fragmento son sentencias, no una clase. Lo último que hace es devolver algo que pueda atender peticiones: un handler o un builder que cree uno.

Tu primera lambda

  1. 1
    Haz clic en Crear mi lambda. Recibes una dirección pública y una clave de edición. La clave es la única forma de volver a entrar, así que guárdala. Nadie puede recuperarla por ti.
  2. 2
    Llegas a su centro de control, con un pequeño servicio REST ya escrito como primera versión. Es solo un punto de partida.
  3. 3
    Pásale la clave de edición a un agente y dile qué construir: escribe versiones nuevas a través de MCP. O abre Código y escríbelo tú: Comprobar compila sin guardar nada y te dice qué opina el compilador, con archivo y línea.
  4. 4
    Haz clic en Desplegar. Ya está en línea. Antes de eso no se puede acceder a nada, y cada vez que vuelves a desplegar alargas el tiempo que sigue en línea.

El centro de control

El enlace de edición abre un centro de control, no un cuadro de texto: aquí casi todo el código lo escriben agentes, así que lo primero que ves es cómo está tu lambda. La barra lateral muestra la lambda (si está en línea, su dirección y un botón cuando hay una versión más nueva esperando para ponerse en línea) y sus secciones. Lo que se hace pocas veces, como cambiar la dirección o eliminarla, está en el menú ⋯ de esa barra.

Resumen
Qué es la app, si está en línea, cuántas peticiones tuvo hoy y cuántas fallaron, el último cambio y cuánto espacio le queda.
Documentación
Qué es la app, para quién es y por qué, y por qué está hecha como está: la escriben los agentes y se guarda con cada versión.
Cambiar
Di qué debería ser distinto y el agente de este servidor lo hace mientras miras. Prueba el cambio en un borrador (una copia con una dirección propia) y lo pone en línea cuando funciona. Desactiva Ponerlo en línea al terminar para probar tú el borrador antes. Solo trabaja en tu app: si lo que pides no tiene que ver con ella o busca hacer daño, lo rechaza y te dice por qué.
Borradores
Cambios que se prueban antes de ponerlos en línea, cada uno en su propia dirección y con sus propios datos de prueba. Al abrirlo, un borrador tiene su propio código, datos de prueba y logs. La sección aparece en cuanto hay un borrador.
Datos
Lo que la lambda guarda mientras se ejecuta, compartido por todas las versiones: la base de datos, el workspace y los secretos, cada uno en su pestaña. Mira las tablas y los archivos, sube archivos, define secretos o activa y desactiva un tipo. La vista simple lo muestra en cuanto la app guarda algo.
Versiones
Qué cambió cada versión, qué se pidió y la diferencia con la anterior. Desde aquí despliegas o vuelves atrás, o empiezas un borrador a partir de cualquiera de ellas.
Despliegues
Qué estuvo en línea y cuándo, y qué lo desconectó.
Estadísticas
Peticiones, fallos, tiempos de respuesta y las rutas más pedidas, en la última hora o el último día.
Logs
Sus peticiones, lo que imprimió y el stack trace de cualquier error, en tiempo real.
Código
Todos los archivos de una versión, su código y sus recursos, en un árbol junto al editor, con el espacio que ocupan y si el público puede acceder a ellos. Elige una versión anterior encima para leer esa. Comprobar compila, Guardar crea una versión y Desplegar la pone en línea. En un borrador, Guardar lo guarda en el borrador y lo muestra en la dirección del borrador. Ctrl-S guarda; F12 va a una declaración.
Pruebas
Cómo se prueba la app automáticamente, con los scripts y los datos de prueba necesarios. Solo en la vista completa.

Todas las secciones funcionan igual: su título, un ⓘ que la explica, sus acciones a la derecha y, si tiene más de una vista, una fila de pestañas debajo. La vista completa agrupa las secciones: cómo la encuentra la gente, dónde se hace un cambio, las versiones y los datos, y cómo se ejecuta.

El tráfico y los logs se guardan en memoria, para mirarlos, no para conservarlos: si el servidor se reinicia, empiezan de cero. Las versiones y el historial de despliegues sí se guardan.

Explicar el porqué

Una versión es el código y, si quieres, dos notas sobre él: la especificación, qué quiere el usuario y por qué, con sus palabras si se puede, y el cambio, una línea sobre lo que hace la versión. Se muestran junto al diff en el historial de versiones, así que el porqué se queda junto al qué: para ti y para el próximo agente que lea el historial antes de tocar nada.

POST /api/v1/lambdas/{editorKey}/versions
{
  "files": [ { "name": "lambda.cs", "code": "..." } ],
  "specification": "Un libro de visitas que la gente pueda firmar; las entradas tienen que sobrevivir a un reinicio",
  "change": "Guarda las entradas en la base de datos para que sobrevivan a un reinicio"
}

Los agentes pasan esos mismos dos campos a write_code. En Código, al guardar se te pide el cambio. Los dos son opcionales; una especificación larga se recorta a 4000 caracteres y un cambio a 500, en vez de rechazarse. Un borrador tiene sus propios dos campos, y la versión en la que se fusiona se queda con ellos.

Documentación y pruebas

Cada versión guarda, junto a su programa, lo que está escrito sobre ella: su documentación (qué es la app, para quién es y por qué, y por qué está hecha como está) y sus pruebas: cómo comprobar automáticamente que funciona, con los scripts y los datos de prueba necesarios. Los agentes las escriben con una lambda nueva y las mantienen al día con cada cambio. El próximo agente que cambie la lambda las lee primero, así que sabe para qué sirve la app y qué tiene que seguir funcionando, algo que el código por sí solo no dice.

docs/product.md
qué es la app, para quién es, qué hace la gente con ella y por qué
docs/decisions.md
las decisiones técnicas, y por qué se tomaron
tests/README.md
cómo se prueba la app automáticamente, y cómo ejecutar las pruebas
tests/…
los scripts y los datos de prueba que usan las pruebas

Son archivos de su código como cualquier otro, en las carpetas docs y tests: el historial muestra qué cambió en ellos una versión, volver atrás trae de vuelta la documentación que era cierta para esa versión, y un borrador tiene su propia copia, que se pone en línea con él. Nunca se compilan ni se sirven, y cuentan para el límite de lo que puede ocupar una versión.

En el centro de control, Documentación muestra las páginas para leer, y Pruebas cómo se prueba la app y los archivos que la acompañan; la versión se elige igual que para sus archivos. Ahí también se puede editar una página, lo que guarda la siguiente versión. La vista sencilla llama a la documentación Acerca de y solo muestra para qué sirve la app: para corregirla, díselo al agente.

Se escriben en el idioma que usas con el agente, para quien cambie la app después, sea una persona o un agente. No son una copia del código: dicen para qué sirve la app, y por qué.

Cambiarla sin riesgo

Una versión nunca cambia una vez guardada, y eso es lo que hace que valga la pena conservarlas todas: cualquiera de ellas se puede comparar y volver a poner en línea exactamente como estaba. Para cambiar una lambda que la gente usa, prueba antes el cambio en un borrador.

  1. 1
    Empiézalo desde cualquier versión en Versiones, o deja que lo empiece el agente. Es una copia del código y los recursos de esa versión, con su documentación y sus pruebas, y de los datos de la lambda.
  2. 2
    Cámbialo tantas veces como haga falta, en Código o pidiéndoselo al agente. Su vista previa responde en una dirección propia, /features/…/, con datos de prueba propios. Los visitantes de la lambda no ven nada de esto, y nada de lo que escribe llega a los datos de la lambda.
  3. 3
    Poner en línea cuando esté bien: se convierte en la siguiente versión, con sus notas, y queda en línea. El borrador desaparece con ello, junto con su vista previa y sus datos de prueba.
POST /api/v1/lambdas/{editorKey}/features
{ "name": "Ranking" }

PUT  /api/v1/lambdas/{editorKey}/features/{feature}/files?deploy=true
POST /api/v1/lambdas/{editorKey}/features/{feature}/merge
{ "deploy": true }

Se puede trabajar en varios borradores a la vez. Solo uno que esté al día con la versión más nueva puede ponerse en línea, para que nunca deshaga una versión guardada después de que empezara el borrador. Si antes se puso otro en línea, lleva sus cambios a este (o pídeselo al agente) y marca el borrador como al día. Nada se pone en línea solo; es a propósito. La API llama feature a un borrador y merge a ponerlo en línea.

Código y recursos

Una versión son tantos archivos como haga falta, en dos partes. Su código es todo archivo salvo sus recursos: sus archivos .cs se compilan, estén en la carpeta que estén, como en cualquier proyecto de C#, y todos los demás se guardan con la versión y nunca se compilan ni se sirven: su documentación, sus pruebas, aquello a partir de lo que se genera un front end. Sus recursos, en resources/, son lo que lee y sirve mientras se ejecuta (páginas, scripts, estilos, imágenes, las migraciones de la base de datos) y se alcanzan desde el código como Resources.

lambda.cs           the snippet: what it returns is served
Shelf.cs            more C#, compiled beside it
models/Book.cs      C# in a folder, compiled the same
docs/ tests/        what is written about it
frontend/           whatever else - kept, never compiled or served
resources/          what it reads and serves while it runs

Los tipos no tienen por qué estar debajo del código que los usa. En Código, haz clic en + junto al código y escribe un nombre: un archivo .cs se compila junto al fragmento, en el mismo namespace, esté en la carpeta que esté, así que no hay que importar nada para usarlo. Un nombre sin extensión y sin carpeta se toma como C#.

lambda.cs
var shelf = new Shelf();

return Inline.Create()
             .Get(() => shelf.All())
             .Post((Book book) => shelf.Add(book));
Shelf.cs
public sealed class Shelf
{
    private readonly List<Book> _books = [];

    public IEnumerable<Book> All() => _books;

    public Book Add(Book book)
    {
        _books.Add(book);
        return book;
    }
}

public record Book(string Title, string Author);

Cómo se organiza el código depende de quien lo escribe: una carpeta para los tipos, otra para las fuentes de un front end, otra para scripts. Todo archivo .cs se compila dentro de la app, así que el C# que no forma parte de ella (una prueba, una herramienta aparte) no debe estar en el código como archivo .cs. El código y los recursos de una versión comparten un único espacio, que muestra el resumen.

Servir una página

Hay dos formas de servir una página, y una más para lo que la gente sube junto a ella.

Una página escrita en el código

Sirve para algo pequeño. La página forma parte del fragmento.

var page = Resource.FromString("""
                              <!doctype html>
                              <title>Mine</title>
                              <h1>It works</h1>
                              """)
                   .Type(new ContentType("text/html; charset=utf-8"));

return Content.From(page);

Una carpeta de archivos reales

Lo que necesitas para cualquier cosa con hoja de estilos y script. Los archivos son recursos de la versión y se sirven tal como están escritos. Nada los compila.

return Layout.Create()
             .Add("api", api)
             .Add(Resources.App("site"));

Archivos subidos, desde los datos

Para lo que la gente sube o la lambda crea (fotos, documentos), servido junto a la app. No para las páginas de la propia app: esas van en los recursos, donde se versionan junto con el código que las necesita.

return Layout.Create()
             .Add("api", api)
             .Add("uploads", Workspace.Files("uploads"))
             .Add(Resources.App("site"));

Un frontend, paso a paso

La segunda forma, completa. Todas las demos sirven su página así, desde resources/web: abre demo-crud para ver una. Las demos son de solo lectura; su clave de edición es su nombre.

  1. 1
    En Código, haz clic en + junto a los recursos y escribe site/index.html: pasa a ser resources/site/index.html. Un nombre con barra pone el archivo en una carpeta; un nombre con extensión se toma como el tipo de archivo que indica.
  2. 2
    Añade site/app.css y site/app.js de la misma forma. Tu página los enlaza por su nombre, como en href="app.css", porque la carpeta es la raíz de lo que se sirve, no parte de la dirección.
  3. 3
    Para todo lo que no sea texto, como una imagen o una fuente, abre un archivo de site y usa el botón de subir que está junto a los recursos: va a parar a la misma carpeta. Un PNG no se puede escribir en un editor de texto, así que esa es la forma de meterlo.
  4. 4
    En lambda.cs, sirve la carpeta:
    return Layout.Create().Add(Resources.App("site"));
  5. 5
    Haz clic en Desplegar. site/index.html responde en /, site/app.css en /app.css, y cualquier dirección que no coincida con un archivo se responde con la página. Así, un frontend con su propio enrutamiento sigue funcionando cuando alguien recarga en un enlace profundo.
  6. 6
    Añade una API al lado y la página tendrá con quién hablar:
    var api = Inline.Create().Get("notes", () => notes);
    
    return Layout.Create()
                 .Add("api", api)
                 .Add(Resources.App("site"));

Aquello a partir de lo que se compila

Una parte de una lambda puede generarla una herramienta de compilación en lugar de escribirse tal como se sirve o se compila: compilada, empaquetada o generada. La versión guarda lo que produce la herramienta, como sus recursos o como su código, y los archivos a partir de los que lo produce forman parte de su código, en una carpeta propia: frontend/, por ejemplo, con un README que explica cómo se compila. Tu agente cambia esos archivos, ejecuta la compilación donde trabaja y guarda ambas cosas en la misma versión. Esta plataforma no compila nada.

frontend/           what it is built from, in whatever shape the tool wants
frontend/README.md  how it is built, and where the build goes
frontend/.gitignore what the build installs or keeps for itself, left out
resources/web/      what the build wrote, if it makes resources
*.cs                what it wrote, if it makes code

# run the build where you work, then
git add -A && git commit -m "…" && git push -o deploy

Como la documentación, pertenecen a la versión: se comparan en el historial, se revierten, se copian en un borrador, se clonan, se descargan y se publican con el resto del código, y nunca se compilan ni se sirven. En el centro de control están en Código, con todos los demás archivos de la versión.

Lo que se escribe tal como se sirve o se compila no necesita nada de esto. Lo que una compilación instala o guarda para sí, como node_modules, nunca forma parte de una versión: un .gitignore en su carpeta lo deja fuera.

Una versión y sus datos

Una lambda guarda archivos en dos lugares, y el editor los muestra por separado: Código contiene los archivos de una versión (el programa) y Datos contiene el workspace (lo que el programa guarda). La diferencia está en de quién son. Los archivos de una versión pertenecen a esa versión; los datos pertenecen a la lambda, y todas las versiones los comparten. Cada uno tiene su propio espacio: el código y los recursos de una versión comparten uno, y la base de datos y el workspace de la lambda comparten el otro.

En una versiónEn los datos
qué contieneel código y los recursos: el programa, frontend incluido, y su documentación, sus pruebas y todo aquello a partir de lo que se compilalo que escribe la lambda o sube alguien
cuándo cambianunca: un cambio es una versión nuevaen cuanto se escribe algo en ellos
un desplieguepone en línea exactamente estos archivosnunca los toca
volver atrástrae de vuelta los archivos anterioresno les afecta: todas las versiones los comparten
un borradorempieza como una copia de ellostrabaja con una copia de ellos
cuándo desaparececon las versiones antiguas, al pasar el límitecon la lambda, o cuando desactivas el workspace
cómo se accede desde el códigoResourcesWorkspace

No pueden estar en un solo lugar. Si lo estuvieran, un despliegue borraría todo lo que tu lambda haya escrito desde entonces, o nunca se podría quitar nada de lo que publica. Un juego con ranking quiere lo segundo; la página que sirve, lo primero. Por eso la página va en la versión y el ranking, en los datos.

Guardar registros

Los registros (entradas, cuentas, pedidos, votos) van en la base de datos: una base de datos SQLite propia de la lambda, que se activa en Datos. El código abre una conexión con Database.GetConnection() y lee y escribe los datos mediante Entity Framework Core, con un contexto propio que mapea las tablas:

// resources/migrations/V1__Create_notes.sql:
//   CREATE TABLE notes (id INTEGER PRIMARY KEY, text TEXT NOT NULL);

using (var connection = Database.GetConnection())
{
    new Evolve(connection) { Locations = [Resources.Root + "migrations"] }.Migrate();
}

return Inline.Create()
             .Get("notes", () =>
             {
                 using var db = new Notes(Database.GetConnection());

                 return db.Entries.OrderBy(n => n.Id).Select(n => n.Text).ToList();
             })
             .Post("notes", (NoteInput input) =>
             {
                 using var db = new Notes(Database.GetConnection());

                 db.Entries.Add(new Note { Text = input.Text });

                 return db.SaveChanges();
             });

record NoteInput(string Text);

class Note
{
    public long Id { get; set; }

    public string Text { get; set; }
}

// maps the table the migration made, on the connection it is handed
class Notes(SqliteConnection connection) : DbContext
{
    public DbSet<Note> Entries => Set<Note>();

    protected override void OnConfiguring(DbContextOptionsBuilder options)
        => options.UseSqlite(connection, contextOwnsConnection: true);

    protected override void OnModelCreating(ModelBuilder model)
        => model.Entity<Note>().ToTable("notes");
}

Sus tablas las crean las migraciones: archivos SQL que van con la versión en resources/migrations/ y que Evolve aplica en orden cuando arranca la lambda, cada uno una sola vez, así que una versión nueva solo ejecuta lo que es nuevo. Nunca cambies una migración que ya se aplicó; un cambio en una tabla es el siguiente archivo.

Como todos los datos, la base de datos la comparten todas las versiones, desplegar o volver atrás no la toca, y un borrador trabaja con una copia. En Datos ves sus tablas y sus filas, que la vista simple llama registros. Descargar como proyecto .NET la incluye como un archivo SQLite normal.

Crea un contexto donde lo necesites y libéralo después, y úsalo de forma síncrona: ToList y SaveChanges, no ToListAsync y SaveChangesAsync. Las tablas las crean las migraciones, nunca Entity Framework. La demo demo-crud hace todo esto.

Guardar archivos

Workspace es un directorio privado que tu lambda puede leer y escribir: el lugar para archivos, como las fotos que sube alguien, un documento que genera o un modelo que carga. Los registros van en la base de datos, y lo que se sabe de un archivo (quién lo subió, cuándo) también es un registro.

// uploads go into a folder of their own, served as they are
Workspace.CreateFolder("photos");

return Layout.Create()
             .Add("photos", Workspace.Files("photos"))
             .Add("upload", Inline.Create().Post(async (Stream body) =>
             {
                 using var content = new MemoryStream();

                 await body.CopyToAsync(content);

                 Workspace.WriteBytes($"photos/{Guid.NewGuid():N}.jpg", content.ToArray());
             }));

También tienes ReadBytes, WriteBytes, Delete, List, CreateFolder y Tree/Files/App para servirlo. No se puede acceder a nada más del sistema de archivos.

Claves y contraseñas

Una clave de API, una contraseña o un token va en los secretos, no en el código, donde lo tendrían cada versión, cada descarga y cualquiera que lea el historial. El código lee un secreto por su nombre:

var weather = new System.Net.Http.HttpClient();

weather.DefaultRequestHeaders.Add("X-Api-Key", Secret.Read("WEATHER_API_KEY"));

return Inline.Create()
             .Get("today", async () => await weather.GetStringAsync("https://weather.example/today"));

Activa los secretos en Datos y define ahí el valor. Una vez guardado, no se vuelve a mostrar, ni a ti ni a un agente: solo puedes reemplazarlo. La lista dice qué nombres lee el código sin que haya todavía un valor, y el resumen los pide. Secret.Exists dice si un secreto está definido, para el código que funciona sin él. Como todos los datos, los secretos los comparten todas las versiones, y un borrador trabaja con una copia.

Se guardan cifrados, con una clave que no está en la base de datos. En un proyecto descargado, Secret.Read("NAME") lee la variable de entorno NAME: los valores se quedan aquí.

WebSockets

Funcionan, y no son un añadido de última hora. La demo demo-game empareja jugadores y ejecuta cada partida en el servidor. La forma más simple son tres callbacks:

var room = new ConcurrentDictionary<IReactiveConnection, string>();

var socket = Websocket.Functional()
                      .OnOpen(c => { room[c] = "someone"; return ValueTask.CompletedTask; })
                      .OnMessage(async (c, text) =>
                      {
                          foreach (var other in room.Keys)
                          {
                              await other.WritePayloadAsync(text);
                          }
                      })
                      .OnClose((c, _) => { room.TryRemove(c, out _); return ValueTask.CompletedTask; });

return Layout.Create().Add("chat", socket);

Cuando la página solo escucha (un contador, un feed, un marcador), los server-sent events son más sencillos: una única respuesta larga en la que el servidor sigue escribiendo y que el navegador reconecta por sí solo. La demo demo-live envía así cada voto a todos los que la están viendo. De un modo u otro, el servidor envía lo que cambió. Una página que vuelve a preguntar cada pocos segundos envía una petición cada vez, haya cambiado algo o no, y aun así llega tarde.

Hay un detalle que sorprende a todo el mundo: un navegador no puede poner cabeceras en el handshake de un websocket. Pasa lo que necesite el handler en la query, donde lo lee desde connection.Request.Header.Query, o envía los secretos en el primer mensaje.

Lo que no te deja hacer

Tu código se ejecuta en un servidor compartido, así que parte de C# se rechaza antes de compilar: iniciar procesos, abrir tus propios sockets, cargar ensamblados, acceder al sistema de archivos fuera de tu workspace y usar reflexión para saltarte cualquiera de esas reglas. Lo mismo ocurre con esperar una tarea con .Result o .Wait() en lugar de usar await: las peticiones se ejecutan en un hilo por núcleo, y la tarea tendría que terminar en el mismo hilo que la está esperando.

Todo lo demás está disponible, incluida toda la API de módulos de GenHTTP. Si algo se rechaza, te decimos en qué línea y por qué, no solo que falló.

Llévate tu código

En el editor, Descargar como proyecto .NET te da todo listo para llevártelo: una solución que puedes abrir, ejecutar con dotnet run y conservar. Solo necesita el paquete de GenHTTP e incluye un Dockerfile para compilarla y ejecutarla como contenedor.

Tu fragmento pasa a ser Project.cs, y Program.cs sirve lo que devuelve. Tus otros archivos llegan exactamente como los escribiste y donde estaban: los recursos en resources, la documentación en docs y las pruebas en tests. Workspace y Resources se convierten en dos carpetas junto al programa, con los mismos métodos, aparte en una carpeta Platform, así que no tienes que cambiar nada de tu código. Secret lee allí las variables de entorno con el mismo nombre; los valores se quedan aquí. Database abre database/database.db, que la descarga incluye con los registros que guardó tu app.

Conviene saberlo antes de crear nada aquí: lo que escribes es tuyo y te lo llevas entero. Ejecutarlo en esta máquina no te ata a esta máquina.

Trabajar con git

Cada lambda es también un repositorio git. Clonar, en el resumen del centro de control y junto a su código, tiene su dirección (la dirección de tu editor con el nombre de la app detrás), y git clone te da el proyecto que te da Descargar, con cada versión como un commit de main, etiquetado v1, v2 y así sucesivamente, y cada borrador como una rama. Ábrelo en tu propio editor, pásaselo a tu agente de programación, ejecútalo con dotnet run.

git clone https://genhttp.dev/editor/<editor key>/my-app.git
cd my-app
# change, commit
git push -o deploy

Haz push y ya está aquí. Cada commit enviado a main se convierte en la siguiente versión, con su primera línea como el cambio que hizo (se compila antes y se rechaza si no compila), y git push -o deploy la pone en línea. Una rama que envíes se convierte en un borrador, con su vista previa en línea en una dirección propia; envíala a main, o añade -o merge a su último push, y será la siguiente versión. Lo que la plataforma añade alrededor de tu código para convertirlo en un proyecto (Program.cs, el archivo de proyecto, Platform) no forma parte de tu app, así que un push que lo cambie se rechaza y explica por qué. AGENTS.md en el repositorio le cuenta el resto a un agente de programación.

La dirección contiene tu clave de edición, igual que la dirección del editor: quien la tenga puede hacer push. Lo que guarda tu app (sus registros, sus archivos, sus claves y contraseñas) nunca está en el repositorio.

Publicar el código

Si lo que creaste puede ayudar a otras personas, publica su código: abre Código abierto en el centro de control, elige una licencia (MIT, salvo que quieras otra) y actívalo. Su código tendrá su propia página entre las apps de código abierto, donde cualquiera puede leerlo, darle una estrella, descargar cualquier versión como el mismo proyecto que te da Descargar, con la licencia al lado, o clonar cada versión con git.

Se publican todas las versiones, también las anteriores, con todo su código (su documentación y sus pruebas incluidas) y el cambio que hizo cada una. Lo que conserva la app nunca se publica (sus registros, los archivos que guardó, los valores de sus claves y contraseñas), como tampoco lo que pediste con tus propias palabras ni quién usa la app. Si lo desactivas, la página desaparece; sus estrellas se conservan para cuando vuelvas a publicarlo.

Todo lo que hay en el código se hace público, incluidas las versiones anteriores. Una clave o una contraseña va en Claves y contraseñas, dentro de Datos, nunca en el código, esté publicado o no.

Que lo haga un agente

Hay un endpoint MCP en /mcp. Conecta un agente y podrá hacer todo lo que hace el editor: leer la guía, leer una demo completa, escribir archivos, compilarlos y desplegar. Por debajo es la misma API.

El agente explica el porqué sobre la marcha (write_code recibe la especificación y el cambio) y puede revisar lo que desplegó: read_logs devuelve las peticiones recientes de la lambda, lo que imprimió y el stack trace de cualquier excepción. Así un agente comprueba que su código funciona en vez de suponerlo. Tú ves lo mismo en el centro de control. Escribe la documentación y las pruebas a medida que trabaja, las lee antes de cambiar nada y ejecuta las pruebas contra la dirección de un borrador antes de ponerlo en línea. A una página pensada para que la encuentren le pone un título, una descripción, un icono y una vista previa para cuando alguien comparte su enlace. Al pie de las páginas que construye añade una línea pequeña que dice que se hicieron con GenHTTP Lambda; dile que prefieres no tenerla y la quita.

Más sobre esto →