<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Guides on SAM</title><link>https://sam-mesh.dev/docs/guides/</link><description>Recent content in Guides on SAM</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://sam-mesh.dev/docs/guides/index.xml" rel="self" type="application/rss+xml"/><item><title>Exposing services</title><link>https://sam-mesh.dev/docs/guides/exposing-services/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://sam-mesh.dev/docs/guides/exposing-services/</guid><description>&lt;p>A node does not publish any service by default. You declare the services it
offers in &lt;code>sam-node.yaml&lt;/code>. This guide covers the three kinds of service a
node can serve and what the mesh policy must contain before anyone can reach
them.&lt;/p>
&lt;h2 id="the-configuration-file">The configuration file&lt;/h2>
&lt;p>&lt;code>sam-node&lt;/code> reads &lt;code>sam-node.yaml&lt;/code> from the working directory, or the file
named by &lt;code>--config&lt;/code>. Both &lt;code>join&lt;/code> and &lt;code>run&lt;/code> read it, because labels are
declared at enrollment. A minimal file with one service:&lt;/p></description></item><item><title>Connecting agents</title><link>https://sam-mesh.dev/docs/guides/connecting-agents/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://sam-mesh.dev/docs/guides/connecting-agents/</guid><description>&lt;p>An agent uses the mesh through the &lt;code>sam-node&lt;/code> that runs on its own machine.
The node is an MCP server, so you can point any MCP client at it. This guide
gives the configuration for the common clients and explains what the agent
gets.&lt;/p>
&lt;h2 id="what-every-client-needs">What every client needs&lt;/h2>
&lt;p>Three values, all printed by &lt;code>sam-node run --daemonize&lt;/code>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>The endpoint&lt;/strong>: &lt;code>http://127.0.0.1:8080/mcp&lt;/code> (Streamable HTTP).&lt;/li>
&lt;li>&lt;strong>The token&lt;/strong>: the contents of &lt;code>~/.config/sam-mesh/api-token&lt;/code>, or the
&lt;code>SAM_API_TOKEN&lt;/code> you started the node with. It goes in the header
&lt;code>X-Sam-Authentication: Bearer &amp;lt;token&amp;gt;&lt;/code>.&lt;/li>
&lt;li>&lt;strong>The socket&lt;/strong>: &lt;code>~/.config/sam-mesh/sam.sock&lt;/code>. Anything the agent runs in a
shell can use the socket without a token. This is the easier way to reach
the node&amp;rsquo;s &lt;code>/v1&lt;/code> inference endpoint from scripts.&lt;/li>
&lt;/ul>
&lt;p>The node must be running before the client starts. MCP clients start and
manage stdio servers themselves, but &lt;code>sam-node&lt;/code> is an HTTP server that they
connect to. You can run &lt;code>sam-node run --daemonize&lt;/code> as often as you like, so it
is safe to put it in a shell profile or to let the agent run it.&lt;/p></description></item><item><title>Headless enrollment</title><link>https://sam-mesh.dev/docs/guides/headless-enrollment/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://sam-mesh.dev/docs/guides/headless-enrollment/</guid><description>&lt;p>Servers, containers and routers cannot complete an interactive login: there
is no browser, and no person to log in. Such a machine enrolls in one of two
ways: with an OIDC token that it already holds, or with a bootstrap token
that an operator mints for it. This guide covers both, and then explains
what happens when the credential of such a node expires.&lt;/p>
&lt;h2 id="with-an-oidc-token-that-the-workload-already-has">With an OIDC token that the workload already has&lt;/h2>
&lt;p>If the platform gives the workload a token from an issuer that the control
plane trusts, no operator step is needed. On Kubernetes this is a projected
service account token with the right audience:&lt;/p></description></item><item><title>Kubernetes</title><link>https://sam-mesh.dev/docs/guides/kubernetes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://sam-mesh.dev/docs/guides/kubernetes/</guid><description>&lt;p>This guide deploys a control plane, a router and a console into a cluster
with the &lt;code>sam-mesh&lt;/code> Helm chart, then puts services on the mesh with the
&lt;code>sam-node&lt;/code> chart. The last section lists the settings to change when you
move from a test cluster to one that you keep. The public testnets run this
setup on GKE. Their manifests are in &lt;code>.github/k8s/&lt;/code> in the repository.&lt;/p>
&lt;h2 id="what-gets-deployed">What gets deployed&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Component&lt;/th>
 &lt;th>Kind&lt;/th>
 &lt;th>Notes&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>sam-control-plane&lt;/code>&lt;/td>
 &lt;td>Deployment (2 replicas)&lt;/td>
 &lt;td>Stateless. All state is in PostgreSQL.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>PostgreSQL&lt;/td>
 &lt;td>StatefulSet&lt;/td>
 &lt;td>In-cluster by default (&lt;code>database.postgres.deployInternal&lt;/code>). You can point the chart at your own database instead.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>sam-router&lt;/code>&lt;/td>
 &lt;td>StatefulSet&lt;/td>
 &lt;td>A PVC holds &lt;code>router.key&lt;/code>, so the peer ID survives rescheduling.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>sam-console&lt;/code>&lt;/td>
 &lt;td>Deployment&lt;/td>
 &lt;td>Optional (&lt;code>console.enabled&lt;/code>).&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>bootstrap Job&lt;/td>
 &lt;td>Job (post-install hook)&lt;/td>
 &lt;td>Seeds the mesh policy and mints the router&amp;rsquo;s bootstrap token.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Gateway + HTTPRoute&lt;/td>
 &lt;td>Gateway API&lt;/td>
 &lt;td>Optional (&lt;code>gateway.enabled&lt;/code>). Routes the enrollment paths and the console.&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>The chart does not include an identity provider, and the control plane needs
one to start. The cluster&amp;rsquo;s own OIDC issuer is a good choice, because every
pod can then enroll with a projected service account token and no secret has
to be distributed.&lt;/p></description></item><item><title>Cloud Run</title><link>https://sam-mesh.dev/docs/guides/cloud-run/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://sam-mesh.dev/docs/guides/cloud-run/</guid><description>&lt;p>&lt;code>sam-one&lt;/code> serves its HTTP API, the console and the router&amp;rsquo;s WebSocket
transport on one port. That is the shape Cloud Run expects. This guide
deploys it there, joins nodes from anywhere, and lists what changes when
&lt;code>sam-one&lt;/code> runs on Cloud Run. The same steps apply to any platform that
forwards HTTP and WebSockets to a container.&lt;/p>
&lt;h2 id="1-build-and-push">1. Build and push&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">PROJECT&lt;/span>&lt;span class="o">=&lt;/span>my-project
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">REGION&lt;/span>&lt;span class="o">=&lt;/span>us-central1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">IMG&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">REGION&lt;/span>&lt;span class="si">}&lt;/span>-docker.pkg.dev/&lt;span class="si">${&lt;/span>&lt;span class="nv">PROJECT&lt;/span>&lt;span class="si">}&lt;/span>/sam-mesh/sam-one:latest
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker build -f Dockerfile.sam-one -t &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$IMG&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> .
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">gcloud auth configure-docker &lt;span class="si">${&lt;/span>&lt;span class="nv">REGION&lt;/span>&lt;span class="si">}&lt;/span>-docker.pkg.dev
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker push &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$IMG&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="2-deploy">2. Deploy&lt;/h2>
&lt;p>Cloud Run has no persistent disk, so the join and admin tokens are set
through environment variables. Without this, a new instance would generate
new tokens and nodes that enrolled earlier could not renew.&lt;/p></description></item></channel></rss>