So funktioniert es
Sie schreiben ein C#-Snippet. Was es zurückgibt, ist in wenigen Sekunden unter einer öffentlichen HTTPS-Adresse erreichbar. Hier steht alles Wichtige – in der Reihenfolge, in der Sie es brauchen.
Was ein Lambda ist
Ein Lambda ist ein Snippet, das einen GenHTTP-Handler zurückgibt. Die Plattform kompiliert es, lädt es und hängt das Ergebnis unter Ihrer eigenen Adresse ein. Kein Projekt, keine Build-Datei, keine using-Anweisungen: Alle GenHTTP-Module sind schon importiert.
return Content.From(Resource.FromString("hello"));
Das ist bereits ein vollständiges Lambda. Unter /lambda/your-key/ deployt, beantwortet es jeden Request mit „hello“.
Das Snippet besteht aus Anweisungen, nicht aus einer Klasse. Zum Schluss gibt es etwas zurück, das Requests beantworten kann: einen Handler oder einen Builder dafür.
Ihr erstes Lambda
- 1Klicken Sie auf Lambda erstellen. Sie bekommen eine öffentliche Adresse und einen Editor-Schlüssel. Der Schlüssel ist der einzige Weg zurück – heben Sie ihn auf. Niemand kann ihn für Sie wiederherstellen.
- 2Sie landen im Kontrollzentrum. Als erste Version ist schon ein kleiner REST-Dienst angelegt – nur als Startpunkt.
- 3Geben Sie den Editor-Schlüssel einem Agenten und sagen Sie ihm, was er bauen soll – er schreibt über MCP neue Versionen. Oder öffnen Sie Code und schreiben Sie selbst: Prüfen kompiliert, ohne etwas zu speichern, und zeigt die Meldungen des Compilers mit Datei und Zeile.
- 4Klicken Sie auf Deployen. Jetzt ist es online – vorher ist nichts erreichbar. Jedes weitere Deployment verlängert, wie lange es online bleibt.
Das Kontrollzentrum
Der Editor-Link öffnet ein Kontrollzentrum, kein Textfeld. Den meisten Code schreiben hier Agenten, also sehen Sie zuerst, wie es Ihrem Lambda geht. Die Seitenleiste zeigt, ob das Lambda online ist, seine Adresse und seine Bereiche. Wartet eine neuere Version darauf, online zu gehen, erscheint dort ein Button. Was Sie selten brauchen, etwa die Adresse ändern oder das Lambda löschen, steckt im Menü ⋯.
- Übersicht
- Ob es online ist, wie viele Requests es heute hatte und wie viele davon fehlschlugen, die letzte Änderung und wie viel Platz noch frei ist.
- Ändern
- Sagen Sie, was anders sein soll, und der Agent auf diesem Server setzt es um, während Sie zusehen. Er arbeitet in einem Entwurf, probiert die Änderung dort aus und übernimmt sie als nächste Version, sobald sie funktioniert. Schalten Sie Nach Abschluss online stellen aus, um den Entwurf zuerst selbst auszuprobieren.
- Entwürfe
- Änderungen, an denen neben dem Lambda gearbeitet wird: Jede wird unter einer eigenen Adresse ausprobiert und als nächste Version übernommen, sobald alles passt. Geöffnet hat ein Entwurf eigenen Code, eigene Daten und eigene Logs.
- Dateien
- Die Dateien einer Version: Code und Assets, das Programm selbst. Ein Schloss oder ein Globus zeigt, ob sie öffentlich erreichbar sind.
- Daten
- Was das Lambda zur Laufzeit aufbewahrt, für alle Versionen gemeinsam: der Workspace. Hineinsehen, Dateien hochladen und löschen oder ihn ausschalten.
- Versionen
- Was jede Version geändert hat, worum gebeten wurde und der Diff zur vorherigen. Von hier aus deployen oder zurückrollen – oder aus jeder von ihnen einen Entwurf beginnen.
- Deployments
- Was wann online war und warum es offline ging.
- Statistik
- Requests, Fehler, Antwortzeiten und die meistgefragten Pfade der letzten Stunde oder des letzten Tages.
- Logs
- Requests, Ausgaben und Stacktraces von allem, was schiefging – live.
- Code
- Selbst schreiben. Prüfen kompiliert, Speichern legt eine Version an, Deployen stellt sie online. In einem Entwurf behält Speichern den Code im Entwurf, und Vorschau deployen stellt ihn unter der Adresse des Entwurfs online.
Strg+Sspeichert,F12springt zur Deklaration.
Alle Bereiche funktionieren gleich: oben der Titel, ein ⓘ mit Erklärung, rechts die Aktionen und – wo es mehrere Ansichten gibt – darunter eine Reihe von Tabs. Beim Code sind die Tabs seine Dateien.
Traffic und Log liegen im Arbeitsspeicher. Sie sind zum Beobachten da, nicht zum Aufbewahren: Nach einem Neustart des Servers beginnen sie von vorn. Versionen und der Deployment-Verlauf werden gespeichert.
Das Warum festhalten
Eine Version ist der Code plus zwei optionale Notizen: die Spezifikation – was der Nutzer möchte und warum, möglichst in seinen Worten – und die Änderung, eine Zeile dazu, was die Version tut. Beide stehen im Versionsverlauf neben dem Diff. So bleibt das Warum neben dem Was erhalten – für Sie und für den nächsten Agenten, der den Verlauf liest, bevor er etwas ändert.
POST /api/v1/lambdas/{editorKey}/versions { "files": [ { "name": "lambda.cs", "code": "..." } ], "specification": "Ein Gästebuch zum Eintragen; Einträge müssen einen Neustart überstehen", "change": "Speichert Einträge im Workspace, damit sie einen Neustart überstehen" }
Agenten übergeben dieselben beiden Felder an write_code. Unter Code wird beim Speichern nach der Änderung gefragt. Beides ist optional. Zu lange Texte werden gekürzt statt abgelehnt: die Spezifikation nach 4000 Zeichen, die Änderung nach 500. Ein Entwurf hat seine eigenen beiden; wird er übernommen, gehen sie an die neue Version über.
Gefahrlos ändern
Eine Version ändert sich nie mehr, sobald sie gespeichert ist – und genau deshalb lohnt es sich, jede aufzuheben: Jede lässt sich vergleichen und genau so wieder online stellen, wie sie war. Um ein Lambda zu ändern, das Leute nutzen, beginnen Sie stattdessen einen Entwurf.
- 1Beginnen Sie ihn unter Entwürfe oder aus einer beliebigen Version. Er ist eine Kopie von Code und Assets dieser Version und der Daten des Lambdas.
- 2Ändern Sie ihn so oft wie nötig – unter Code oder indem Sie den Agenten darum bitten. Vorschau deployen stellt ihn unter einer eigenen Adresse online,
/features/…/, mit einer eigenen Kopie der Daten. Besucher des Lambdas sehen nichts davon, und nichts, was er schreibt, erreicht die Daten des Lambdas. - 3Klicken Sie auf Übernehmen, sobald alles passt: Der Entwurf wird zur nächsten Version, mit seinen Notizen, und geht auf Wunsch sofort online. Dabei verschwindet er – samt seiner Vorschau und seiner Kopie der Daten.
POST /api/v1/lambdas/{editorKey}/features { "name": "Bestenliste" } PUT /api/v1/lambdas/{editorKey}/features/{feature}/files?deploy=true POST /api/v1/lambdas/{editorKey}/features/{feature}/merge { "deploy": true }
An mehreren Entwürfen kann gleichzeitig gearbeitet werden. Übernehmen lässt sich nur einer, der auf der neuesten Version basiert – damit das Übernehmen nie eine Version rückgängig macht, die nach dem Beginn des Entwurfs gespeichert wurde. Wurde zuerst ein anderer übernommen, holen Sie dessen Änderungen herein – oder bitten Sie den Agenten darum – und geben Sie dann an, dass der Entwurf auf der neuesten Version basiert. Nichts wird von selbst übernommen; das ist Absicht.
Mehrere Dateien
Typen müssen nicht unter dem Code stehen, der sie nutzt. Klicken Sie unter Code neben den Dateien auf +: Die neue Datei wird zusammen mit dem Snippet im selben Namespace kompiliert, also müssen Sie nichts importieren. Ein Name ohne Endung gilt als C#.
var shelf = new Shelf(); return Inline.Create() .Get(() => shelf.All()) .Post((Book book) => shelf.Add(book));
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);
Eine Seite ausliefern
Für eine Seite gibt es zwei Wege – und einen weiteren für das, was Leute daneben hochladen.
Eine Seite, direkt im Code
Gut für Kleines. Die Seite ist Teil des Snippets.
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);
Ein Ordner mit echten Dateien
Das Richtige für alles mit Stylesheet und Script. Die Dateien legen Sie genauso an wie eine C#-Datei. Sie werden ausgeliefert, wie sie sind – nichts wird kompiliert.
return Layout.Create() .Add("api", api) .Add(Assets.App("site"));
Hochgeladene Dateien, aus den Daten
Für das, was Leute hochladen oder das Lambda erzeugt – Bilder, Dokumente –, ausgeliefert neben der App. Nicht für die Seiten der App selbst: Die gehören in einen Ordner mit Dateien, damit sie in derselben Version stecken wie der Code, der sie braucht.
return Layout.Create() .Add("api", api) .Add("uploads", Workspace.Files("uploads")) .Add(Assets.App("site"));
Ein Frontend, Schritt für Schritt
Der zweite Weg im Detail. Jede Demo liefert ihre Seite so aus, aus einem Ordner namens web – öffnen Sie zum Beispiel demo-crud. Demos sind schreibgeschützt; ihr Editor-Schlüssel ist ihr Name.
- 1Klicken Sie unter Code neben den Dateien auf + und geben Sie
site/index.htmlein. Ein Schrägstrich im Namen legt die Datei in einen Ordner. Eine Endung sagt, was für eine Datei es ist. - 2Legen Sie
site/app.cssundsite/app.jsgenauso an. Ihre Seite verweist über den Namen auf sie, etwa mithref="app.css". Denn der Ordner ist die Wurzel dessen, was ausgeliefert wird – kein Teil der Adresse. - 3Für alles, was kein Text ist, etwa Bilder oder Schriften, öffnen Sie eine Datei in
siteund klicken neben den Dateien auf den Upload-Button: Die Datei landet im selben Ordner. Ein PNG kann man nicht in einen Texteditor tippen – das hier ist der Weg. - 4Liefern Sie den Ordner in
lambda.csaus:return Layout.Create().Add(Assets.App("site"));
- 5Klicken Sie auf Deployen.
site/index.htmlantwortet unter/,site/app.cssunter/app.css. Jede Adresse ohne passende Datei bekommt die Seite. So funktioniert ein Frontend mit eigenem Routing auch, wenn jemand einen Deep Link neu lädt. - 6Mit einer API daneben hat die Seite auch einen Gesprächspartner:
var api = Inline.Create().Get("notes", () => notes); return Layout.Create() .Add("api", api) .Add(Assets.App("site"));
Zwei Orte für Dateien
Ein Lambda hat Dateien an zwei Orten, und der Editor zeigt sie getrennt: Dateien enthält die Dateien einer Version – das Programm –, Daten den Workspace – was das Programm aufbewahrt. Der Unterschied ist, wem sie gehören. Die Dateien einer Version gehören zu dieser Version; die Daten gehören dem Lambda, und alle Versionen teilen sie.
| In einer Version | In den Daten | |
|---|---|---|
| Inhalt | Code und Assets: das Programm, samt Frontend | alles, was das Lambda schreibt oder jemand hochlädt |
| Ändert sich | nie – eine Änderung ist eine neue Version | sobald etwas hineingeschrieben wird |
| Ein Deployment | stellt genau diese Dateien online | lässt sie unberührt |
| Zurückrollen | bringt die alten Dateien zurück | keine Wirkung: Alle Versionen teilen sie |
| Ein Entwurf | beginnt als Kopie davon | arbeitet mit einer Kopie davon |
| Wird gelöscht | mit alten Versionen, sobald das Limit überschritten ist | mit dem Lambda oder wenn Sie sie ausschalten |
| im Code erreichbar als | Assets | Workspace |
Ein gemeinsamer Ort geht nicht. Sonst würde ein Deployment entweder alles löschen, was Ihr Lambda seitdem geschrieben hat – oder aus dem, was es ausliefert, ließe sich nie etwas entfernen. Ein Spiel mit Bestenliste braucht das Zweite, die Seite dazu das Erste. Also gehört die Seite in die Version und die Bestenliste in die Daten.
Daten speichern
Workspace ist ein privates Verzeichnis, in dem Ihr Lambda lesen und schreiben darf. Hier gehört alles hin, was einen Request oder ein Deployment überdauern soll.
var notes = new List<string>(); if (Workspace.Exists("notes.json")) { notes.AddRange(JsonSerializer.Deserialize<List<string>>(Workspace.ReadText("notes.json")) ?? []); } return Inline.Create() .Get("notes", () => notes) .Post("notes", (string text) => { notes.Add(text); Workspace.WriteText("notes.json", JsonSerializer.Serialize(notes)); return notes.Count; });
Dazu gibt es ReadBytes, WriteBytes, Delete, List, CreateFolder und zum Ausliefern Tree/Files/App. Sonst ist nichts im Dateisystem erreichbar.
Websockets
Unterstützt – und von Anfang an mitgedacht. Die Demo demo-game bringt Spieler zusammen und führt jede Partie auf dem Server aus. Die einfachste Form sind drei 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);
In diese Falle tappt jeder: Browser können beim Websocket-Handshake keine Header setzen. Übergeben Sie, was der Handler braucht, in der Query – er liest sie aus connection.Request.Header.Query. Secrets schicken Sie als erste Nachricht.
Was nicht erlaubt ist
Ihr Code läuft auf einem gemeinsam genutzten Server. Deshalb wird manches in C# schon vor dem Kompilieren abgelehnt: Prozesse starten, eigene Sockets öffnen, Assemblies laden, auf das Dateisystem außerhalb Ihres Workspace zugreifen – und Reflection, die all das umgehen soll.
Alles andere ist da, auch die komplette API der GenHTTP-Module. Wird etwas abgelehnt, sehen Sie, in welcher Zeile und warum – nicht nur, dass es fehlschlug.
Alles mitnehmen
Mit Als .NET-Projekt herunterladen im Editor bekommen Sie alles als Solution, die Sie öffnen, mit dotnet run starten und behalten können. Sie hat genau eine Paketreferenz und keine Spur dieser Plattform.
Ihr Snippet wird zum Inhalt von Program.cs, in einem Host, der ausliefert, was es zurückgibt. Ihre anderen Dateien kommen genau so mit, wie Sie sie geschrieben haben. Workspace und Assets werden zu zwei Ordnern neben dem Code, mit denselben Methoden – an Ihrem Code ändert sich nichts.
Gut zu wissen, bevor Sie hier etwas bauen: Was Sie schreiben, gehört Ihnen, und Sie können es komplett mitnehmen. Dass es auf unserem Server läuft, bindet es nicht an unseren Server.
Mit einem Agenten arbeiten
Unter /mcp gibt es einen MCP-Endpunkt. Verbinden Sie einen Agenten damit, und er kann alles, was der Editor kann: die Anleitung lesen, eine Demo komplett lesen, Dateien schreiben, kompilieren und deployen. Darunter liegt dieselbe API.
Dabei sagt er, warum er etwas tut – write_code nimmt Spezifikation und Änderung entgegen. Und er kann prüfen, was er deployt hat: read_logs liefert die letzten Requests des Lambdas, seine Ausgaben und die Stacktraces aller Exceptions. So weiß ein Agent, dass sein Code funktioniert, statt es nur anzunehmen. Dasselbe sehen Sie im Kontrollzentrum.