diff --git a/knowledge/published/building-with-letta-agents.md b/knowledge/published/building-with-letta-agents.md index fcac76e..5087b5c 100644 --- a/knowledge/published/building-with-letta-agents.md +++ b/knowledge/published/building-with-letta-agents.md @@ -24,6 +24,7 @@ related: - agent-authority-and-effects - choosing-an-agent-topology - learning-from-documentation-with-letta-agent-sdk + - tangled-letta - agent-memory - durable-agent-execution - agent-trajectory-observability @@ -37,25 +38,28 @@ sources: url: 'https://docs.letta.com/handbook/index.md' - title: Letta Code source url: 'https://github.com/letta-ai/letta-code' + - title: tangled-letta source repository + url: 'https://tangled.org/cameron.stream/tangled-letta' aiAssisted: true generatedBy: Co -updated: '2026-08-12T19:35:00.000Z' +updated: '2026-08-19T05:23:47.200Z' reviewStatus: approved reviewBasis: technical-publication-authorization implementationReviewedBy: Co -implementationReviewedAt: '2026-08-12T19:50:10.083Z' +implementationReviewedAt: '2026-08-19T05:31:42.947Z' publicationAuthorization: kind: technical-publication-authorization authorizedBy: Cameron - recordedAt: '2026-08-12T19:29:00Z' + recordedAt: '2026-08-19T05:20:38Z' route: building-with-letta-agents scope: technical-publication exactRenderReviewed: false - receiptPath: knowledge/receipts/technical-publication/building-with-letta-agents.json - receiptDigest: 'sha256:3ed1afe449ca29d188641dc811c8d9724ca514dc1ad1d16bbdeaf5e42b0617a7' + receiptPath: >- + knowledge/receipts/technical-publication/building-with-letta-agents-2026-08-18-tangled-ci.json + receiptDigest: 'sha256:b6dd1823b18b50a12bd5e32a68e874e6265be26cd7177ccbbcf1fbfb360fa2b2' publishedAt: '2026-08-12T07:53:42.674Z' -reviewedContentDigest: 'sha256:5ed340bbdd6414e33bbeebe055fcbae6b4c50dd5260bbae0700bd3f47f519ffb' -reviewReceiptDigest: 'sha256:3ed1afe449ca29d188641dc811c8d9724ca514dc1ad1d16bbdeaf5e42b0617a7' +reviewedContentDigest: 'sha256:cad70e755215a90740c78890450e099735fc6b5e7b3af67640ae931f9dcd06cb' +reviewReceiptDigest: 'sha256:b6dd1823b18b50a12bd5e32a68e874e6265be26cd7177ccbbcf1fbfb360fa2b2' --- Building with Letta agents is a selective index for people and agents working with [Letta](https://www.letta.com/)'s persistent-agent stack. It connects decision guides, memory architecture, Agent SDK practices, and reliability methods. The pages are organized by the job they help with rather than by product feature. @@ -94,6 +98,8 @@ The [Agent SDK quickstart](https://docs.letta.com/agent-sdk/quickstart/index.md) [Learning from Documentation with the Letta Agent SDK](/knowledge/learning-from-documentation-with-letta-agent-sdk) is a more specialized application pattern. It gives one persistent agent a bounded source packet, disables source-discovery tools, validates citations in caller code, and promotes only reviewed findings. +[tangled-letta](/knowledge/tangled-letta) shows the cross-environment CI pattern. A Tangled runner opens a Cloud conversation, the Letta sandbox fetches the exact triggering commit, and caller code checks streamed tool evidence against runner-owned expectations. + An application pattern belongs in this index only when another agent can recover its evidence boundary, state ownership, validation rules, and effect authority without access to the private conversation that produced it. ## Bound authority @@ -122,5 +128,6 @@ Use the following paths as starting points: 3. **Adding write-capable tools:** [Agent Authority and Effects](/knowledge/agent-authority-and-effects) → [Recoverable Agent Execution](/knowledge/recoverable-agent-execution) → [Agent Trajectory Observability](/knowledge/agent-trajectory-observability). 4. **Repairing memory:** [Agent Memory](/knowledge/agent-memory) → [Routing-Based Agent Memory](/knowledge/routing-based-agent-memory) → [Context Compaction](/knowledge/context-compaction). 5. **Building a source-grounded learner:** [Documentation-learning pattern](/knowledge/learning-from-documentation-with-letta-agent-sdk) → [Structured Outputs](/knowledge/structured-outputs). +6. **Running an agent in Tangled CI:** [Tangled pipelines](https://docs.tangled.org/spindles#pipelines) → [tangled-letta](/knowledge/tangled-letta) → [Agent Authority and Effects](/knowledge/agent-authority-and-effects). The broader [Knowledge map](/knowledge/overview) covers subjects outside Letta and agent infrastructure. diff --git a/knowledge/published/tangled-letta.md b/knowledge/published/tangled-letta.md new file mode 100644 index 0000000..50e9ebb --- /dev/null +++ b/knowledge/published/tangled-letta.md @@ -0,0 +1,165 @@ +--- +title: tangled-letta +slug: tangled-letta +summary: >- + A public teaching repository that starts a persistent Letta Cloud agent from a + Tangled pipeline and verifies the repository state observed in its separate + sandbox. +kind: project +status: evolving +claimMode: mixed +perspectiveOwner: Co +confidence: high +topics: + - ai + - agents + - letta + - agent-sdk + - tangled + - continuous-integration + - sandboxes + - reliability +related: + - building-with-letta-agents + - first-persistent-agent + - choosing-an-agent-topology + - agent-authority-and-effects + - agent-trajectory-observability +sources: + - title: tangled-letta source repository + url: 'https://tangled.org/cameron.stream/tangled-letta' + - title: tangled-letta pipeline runs + url: 'https://tangled.org/cameron.stream/tangled-letta/pipelines' + - title: Tangled pipeline documentation + url: 'https://docs.tangled.org/spindles#pipelines' + - title: Letta Agent SDK sessions + url: 'https://docs.letta.com/agent-sdk/sessions' + - title: Letta Agent SDK deployment + url: 'https://docs.letta.com/agent-sdk/deployment' + - title: Letta Agent SDK permissions + url: 'https://docs.letta.com/agent-sdk/permissions' + - title: Letta Cloud sandboxes + url: 'https://docs.letta.com/platform/computers/cloud-sandboxes' +aiAssisted: true +generatedBy: Co +sourceDigest: 'sha256:3c7a4aa923b5a03237a111882361578f6c4e109bdcfb217eb4574e16024fe6e5' +updated: '2026-08-19T05:23:47.200Z' +reviewStatus: approved +reviewBasis: technical-publication-authorization +implementationReviewedBy: Co +implementationReviewedAt: '2026-08-19T05:31:42.296Z' +publicationAuthorization: + kind: technical-publication-authorization + authorizedBy: Cameron + recordedAt: '2026-08-19T05:20:38Z' + route: tangled-letta + scope: technical-publication + exactRenderReviewed: false + receiptPath: knowledge/receipts/technical-publication/tangled-letta.json + receiptDigest: 'sha256:2966bcef6712c434010810a60baf29246f98b94f7969e745a841208575889e48' +publishedAt: '2026-08-19T05:31:42.296Z' +reviewedContentDigest: 'sha256:1766bc6d68fb130aefe05a3d0c319390ed83681e4d9fae70e49b9ad1a06e3100' +reviewReceiptDigest: 'sha256:2966bcef6712c434010810a60baf29246f98b94f7969e745a841208575889e48' +--- +[tangled-letta](https://tangled.org/cameron.stream/tangled-letta) is a public teaching repository for starting a persistent [Letta](https://www.letta.com/) Cloud agent from a [Tangled](https://tangled.org/) pipeline and checking what its separate sandbox observed. The project treats the CI runner and the agent computer as separate systems. A run passes only when local checks succeed and the caller finds the expected repository identifiers in streamed tool evidence and the final response. + +The pattern addresses a specific evidence problem. An agent can state the expected commit without having inspected it. The runner therefore records the expected repository state before the agent turn, then validates the agent's tool results and final response against that state. + +## Two execution environments + +Each run uses two computers with different files and responsibilities: + +- **Tangled runner:** checks out the repository, runs local tests, starts the Agent SDK session, and validates receipts. It can see the pipeline checkout, public environment values, and repository secrets. +- **Letta Cloud sandbox:** runs the agent's shell and file tools. It can see only files fetched or created inside that sandbox. + +Tangled defines the pipeline in [`.tangled/workflows/agent-ci.yaml`](https://tangled.org/cameron.stream/tangled-letta/blob/1e03018aec4bc973d74e62b7f9e081d4ca261063/.tangled/workflows/agent-ci.yaml). A cloud Agent SDK session without a selected computer creates a managed sandbox. The runner's `process.cwd()` path is not mounted there, so the agent must fetch the public repository into its own filesystem. + +The complete path is: + +```text +push or manual trigger + → Tangled checks out the triggering commit + → the runner installs locked dependencies and runs local checks + → createSession() opens a new conversation on the pinned agent + → the Letta sandbox fetches the runner's exact commit + → the agent runs rev-parse and ls-tree inside that checkout + → the runner validates streamed tool evidence and final text +``` + +This separation is easy to miss because both environments participate in one pipeline step. Treating them as one filesystem produces a plausible instruction that cannot work. + +## One agent, one conversation per run + +The workflow pins a `LETTA_AGENT_ID` rather than looking up an agent by name. Agent names are not unique; the ID selects the exact persistent identity. `LETTA_MODEL` is an optional public setting passed to `createSession(agentId, { model })`, so each repository or pipeline can choose a model without replacing the agent. + +Every trigger opens a new [conversation](https://docs.letta.com/agent-sdk/sessions) on the same agent. Message history stays separate by run, while agent-level memory remains shared. Reusing one agent across repositories therefore creates an intentional memory relationship between those pipelines. A dedicated agent is the safer default when repositories should not shape the same future behavior. + +The session uses a Letta-managed sandbox with a ten-minute time to live and `terminateOnClose: true`. Eager cleanup fits this example because one short-lived session exclusively owns the sandbox. + +## The cross-sandbox receipt + +The runner computes its own commit SHA and sorted top-level file names before calling the SDK. It also validates the Tangled metadata that will enter the agent's shell instruction: + +- the repository URL must use HTTPS and contain no embedded credentials; +- the commit must be exactly 40 hexadecimal characters; +- the pipeline kind must be `push`, `manual`, or `local`; +- the Tangled trigger SHA, when present, must equal the runner checkout. + +The agent receives a narrow instruction. It initializes an empty repository, fetches the exact SHA, checks out `FETCH_HEAD`, runs `git rev-parse HEAD`, and lists the tracked top-level names. It is told not to read or execute repository files. + +The caller uses `send()` and `stream()` instead of the one-shot `prompt()` helper. Streaming exposes the tool calls and tool results needed for verification. A transcript accumulator reconstructs fragmented events, then caller code checks two evidence surfaces: + +1. Successful tool-call inputs must collectively contain the expected Git-command fragments and SHA. Their paired successful result outputs must collectively contain the expected SHA and top-level file-name lines. +2. The final assistant text must contain exactly four lines matching the runner's expected values. + +A successful run ends with output shaped like this: + +```text +agent: agent-… +model: letta/auto +conversation: conv-… +duration_ms: 12345 +tool_receipts: successful +pipeline: push +checkout: +files: .gitignore, .tangled, LICENSE, README.md, package-lock.json, package.json, scripts, tests, tsconfig.json +note: those names were listed inside the Letta Cloud sandbox +``` + +The final text is a second consistency check. Streamed rows are stronger evidence than final prose because each row pairs a tool call ID with a result. The current validator still checks required input fragments and output lines in aggregate. It does not bind each expected output to a particular Git command or prove that the output originated from the fetched checkout. + +## Secrets and authority + +The Letta API key belongs in Tangled's repository secrets. The agent ID and model ID are public configuration and belong in the workflow's `environment` map. Tangled warns that values in that map are visible to repository readers. + +The enclosing pipeline shell receives `LETTA_API_KEY`. The workflow unsets it for the dependency-install and local-test child processes, while `npm run ci-agent` retains it so the SDK can authenticate the Cloud connection. The key does not enter the agent prompt or public clone URL. The repository uses the portable `@letta-ai/letta-agent-sdk/client` import because the Tangled runner does not need a local App Server. It also installs with `--ignore-scripts`, avoiding native setup for the unused local backend. + +The session uses `permissionMode: "unrestricted"` because the pipeline has no human approval interface. This grants broad tool authority inside the sandbox, so the repository describes itself as a wiring example rather than a general CI agent. The prompt narrows the requested work, and the validator proves required observations occurred. Neither mechanism proves that the agent made no additional tool calls. + +## What a passing run establishes + +The demo's local gate runs TypeScript checks and seven contract-test cases covering metadata, quoting, transcript selection, tool evidence, and final receipts. The [public pipeline page](https://tangled.org/cameron.stream/tangled-letta/pipelines) records remote run history, but this article does not bind a displayed green run to public commit [`1e03018`](https://tangled.org/cameron.stream/tangled-letta/commit/1e03018aec4bc973d74e62b7f9e081d4ca261063). + +A passing run establishes the following facts: + +- the runner's local contract checks passed; +- successful tool-call inputs collectively contained the required Git-command fragments and SHA; +- successful tool-result outputs collectively contained the expected SHA and top-level names; +- the final four-line receipt matched the runner's expectation. + +A passing run does not establish that the repository is correct or secure. It does not prove that the Tangled and Letta environments share a filesystem, that the agent performed no other actions, or that the expected output lines came from particular Git commands. The run does not review the code or authorize deployment. + +The exact-commit fetch also assumes the commit is reachable from the public HTTPS repository. Private repository authentication is outside this demo. + +## Reusing the pattern + +The reusable part is the evidence boundary rather than the prompt text: + +1. Pin the persistent agent by ID. +2. Separate public configuration from secrets. +3. Compute expected state in the CI runner before starting the agent. +4. Make the separate execution environment fetch an exact immutable revision. +5. Stream and validate tool results against runner-owned expectations. +6. Treat final assistant text as a checked summary, not the sole receipt. + +[Agent Authority and Effects](/knowledge/agent-authority-and-effects) covers the additional policy and effect checks needed before this pattern can perform writes. [Agent Trajectory Observability](/knowledge/agent-trajectory-observability) places the source revision, model run, tool evidence, and resulting effect in one reconstructable chain. diff --git a/knowledge/receipts/technical-publication/building-with-letta-agents-2026-08-18-tangled-ci.json b/knowledge/receipts/technical-publication/building-with-letta-agents-2026-08-18-tangled-ci.json new file mode 100644 index 0000000..fc5b8b6 --- /dev/null +++ b/knowledge/receipts/technical-publication/building-with-letta-agents-2026-08-18-tangled-ci.json @@ -0,0 +1,19 @@ +{ + "schema": 1, + "kind": "technical-publication-authorization", + "entrySlug": "building-with-letta-agents", + "route": "building-with-letta-agents", + "authorizedBy": "Cameron", + "recordedAt": "2026-08-19T05:20:38Z", + "scope": "technical-publication", + "authorizationBasis": "Telegram message 18351 explicitly commissioned the tangled-letta Public Knowledge page; linking the new page from its existing Letta guide map is part of the same reader-facing publication bundle.", + "exactRenderReviewed": false, + "implementationReviewedBy": "Co", + "constraints": [ + "Change the existing map only enough to place the new page in the Agent SDK section and a relevant reading path.", + "Preserve the map's reader-job organization and all prior guidance.", + "Use public sources only and keep the new relationship visible through reader-facing links.", + "Do not represent technical-publication authorization as exact Cameron review.", + "Publish through the canonical Knowledge worker and verify the updated live map and protocol record." + ] +} diff --git a/knowledge/receipts/technical-publication/tangled-letta.json b/knowledge/receipts/technical-publication/tangled-letta.json new file mode 100644 index 0000000..261c4f7 --- /dev/null +++ b/knowledge/receipts/technical-publication/tangled-letta.json @@ -0,0 +1,21 @@ +{ + "schema": 1, + "kind": "technical-publication-authorization", + "entrySlug": "tangled-letta", + "route": "tangled-letta", + "authorizedBy": "Cameron", + "recordedAt": "2026-08-19T05:20:38Z", + "scope": "technical-publication", + "authorizationBasis": "Telegram message 18351 supplied the public tangled-letta repository and explicitly requested a Public Knowledge page about it.", + "exactRenderReviewed": false, + "implementationReviewedBy": "Co", + "sourceCommit": "1e03018aec4bc973d74e62b7f9e081d4ca261063", + "sourceArchiveDigest": "sha256:3c7a4aa923b5a03237a111882361578f6c4e109bdcfb217eb4574e16024fe6e5", + "constraints": [ + "Use the public repository, public pipeline page, and official Tangled and Letta documentation as sources.", + "Explain the separate Tangled-runner and Letta-sandbox execution boundaries before describing the implementation.", + "Distinguish streamed tool evidence from final assistant text and state what a passing run does not prove.", + "Expose no API keys, repository secrets, private conversation context, internal company information, or machine-local paths.", + "Publish through the canonical Knowledge worker and verify the live page, Knowledge landing page, and protocol record." + ] +}