Latest commit

History

24 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

@smooai/deploy — One agent. AWS serverless or Kubernetes.

Smoo AIlicenselom.smoo.ai

TypeScript / SST v4Helm + ArgoCDverify: tsc + helm lint

Features · Install · Usage · Platform


@smooai/deploy packages the deploy primitives for a smooth-operator-style agent so you don't hand-roll them per service. The same agent ships to AWS serverless or Kubernetes off one set of conventions — you pick the runtime, not the agent.

It gives you two production-shaped paths off the same conventions:

  • AWS serverlessnew SmoothAgentApi(...): an API Gateway WebSocket + (Rust) Lambda + DynamoDB single table + S3 blob bucket + S3 Vectors wiring + gateway-key secret + IAM links, as a single parameterized SST component.
  • Kubernetes / self-host — the smooth-operator Helm chart: an axum /ws server backed by pgvector Postgres, fronted by a WebSocket-friendly Ingress, synced by ArgoCD.

Two real consumers justify the shared package: smooth-operator (the reference WebSocket agent service, uses both surfaces today) and the smooai monorepo (dogfoods the SST constructs piecemeal).

✨ Features

You want…@smooai/deploy gives you
One construct, whole serverless backendSmoothAgentApi: WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM
Composable primitivesWebSocketLambdaApi, DynamoSingleTable exported independently
A Kubernetes path toothe smooth-operator Helm chart + ArgoCD Application
No copy-paste between servicesthe smooth-operator deploy logic, extracted and parameterized
Safe-by-default podsnon-root, read-only rootfs, dropped caps, seccomp RuntimeDefault
WebSocket-aware Ingresslong proxy timeouts + websocket annotations baked into chart defaults

📦 Install

@smooai/deploy is consumed today via a path dep for local development:

// package.json
{
"dependencies": {
"@smooai/deploy": "file:../../deploy/sst"
}
}

Publishing follow-up: publish @smooai/deploy to npm (and the chart to an OCI/HTTP Helm repo) so consumers pin a version instead of a sibling-checkout path. See docs/Consuming.md.

🚀 Usage

AWS serverless — one construct in your sst.config.ts

// consumer's sst.config.ts — inside run()import{SmoothAgentApi}from'@smooai/deploy';constagent=newSmoothAgentApi('SmoothAgent',{// The cargo-lambda output dir holding `bootstrap` (provided.al2023 / arm64).artifactDir: '../../rust/target/lambda/smooai-smooth-operator-lambda',model: 'claude-haiku-4-5',});returnagent.outputs;// { api, table, blobs, vectorBucket }

One new SmoothAgentApi(...) stands up the whole serverless backend and wires the IAM links between the pieces. The smaller building blocks — WebSocketLambdaApi, DynamoSingleTable — are exported too, so you can adopt them independently.

These are SST constructs, not a deployable app. They reference SST's ambient $-globals (sst.aws.*, $interpolate, $app), so import them from inside an SST app's run().

Kubernetes — one helm install

helm upgrade --install smooth-operator helm/smooth-operator \
--namespace smooai-smooth-operator --create-namespace \
--set image.tag=0.1.0 \
--set gateway.keySecretRef.name=smooth-operator-gateway \
--set database.urlSecretRef.name=smooth-operator-db

Postgres with the pgvector extension is an external dependency (the chart does not vendor a Postgres pod). Point database.urlSecretRef at a pgvector-enabled database — see helm/smooth-operator/README.md.

Compose the smaller primitives

SmoothAgentApi is the batteries-included path. When you want to assemble your own topology, the sub-constructs are first-class:

import{WebSocketLambdaApi,DynamoSingleTable}from'@smooai/deploy';// A DynamoDB single table (OLTP + checkpoints + connection registry).consttable=DynamoSingleTable('AgentTable',{});// An API Gateway WebSocket fronting a Rust Lambda, with your own routes.const{ api }=WebSocketLambdaApi('AgentApi',{handler: '../../rust/target/lambda/my-agent-lambda',environment: {SMOOTH_AGENT_DDB_TABLE: table.name},link: [table],// Defaults to the SmooAI protocol routes; override as needed:// routes: [{ route: 'send_message', timeout: '30 seconds' }, …],});

Defaults are sensible: the WebSocket route table covers $connect, $disconnect, send_message, ping, and $default; the gateway URL defaults to https://llm.smoo.ai/v1; the model defaults to claude-haiku-4-5.

📖 Architecture — one agent, two deploy paths

%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart LR
SRC["smooth-operator<br/>Rust agent"]
subgraph aws["AWS serverless · SmoothAgentApi"]
LAM["Rust Lambda"]
STORE[("Dynamo · S3 · Vectors")]
LAM --> STORE
end
subgraph k8s["Kubernetes · Helm + ArgoCD"]
DEP["axum /ws"]
PG[("pgvector Postgres")]
DEP --> PG
end
SRC -->|lambda artifact| LAM
SRC -->|container image| DEP
LAM -.->|OpenAI-compatible| GW[("LLM gateway")]
DEP -.->|OpenAI-compatible| GW
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class SRC warm
class STORE,PG,GW teal
Loading

The same agent ships as a Lambda artifact (serverless) or a container image (k8s). Both speak the same WebSocket protocol and call the same OpenAI-compatible LLM gateway — you pick the runtime, not the agent.

📖 Verified, not vibe-coded

Infra you can't cargo test still has to be verified. This package proves correctness without a live AWS account or cluster:

  • SST constructs typecheck against real SST platform types: pnpm sst install generates .sst/platform, then tsc --noEmit validates the constructs compile against the SDK surface — catching the SST footguns (unlinked resources, ambient-global misuse) that only next build-class checks surface.
  • Helm chart is linted and rendered: helm lint + helm template validate the chart and ArgoCD Application produce valid manifests.
  • kind-cluster smoke (CI): the rendered chart is applied to an ephemeral kind cluster so the manifests actually schedule.
  • Deployed via CI, never locally — local deploys can ship unintended changes; the pipeline owns sst deploy / argocd sync.
%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart TD
U["Construct typecheck<br/>sst install → tsc"] --> C["Conformance<br/>helm lint + template"]
C --> E["kind-cluster smoke<br/>render → apply"]
E --> J["LLM-as-judge evals<br/>multi-turn, scored 0–5"]
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class U teal
class J warm
Loading

Verify locally (no AWS creds, no deploy):

# SST constructscd sst && pnpm install && pnpm sst install && npx tsc --noEmit
# Helm chart
helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator

The full quality pyramid spans repos: the engine's 408 unit tests + LLM-as-judge evals (which caught a multi-turn defect that scored 1/5 → fixed → 5/5) and the widget's live Playwright e2e sit above this package's static + smoke verification.

📖 Constructs reference

ExportWhat it is
SmoothAgentApiThe full serverless backend (WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM).
WebSocketLambdaApiAPI Gateway WebSocket fronting a Rust Lambda, with a configurable route table.
DynamoSingleTableThe single-table Dynamo schema (OLTP + checkpoints + connection registry).

SmoothAgentApi args (selected)

ArgDefaultPurpose
artifactDir(required)The cargo lambda output dir holding bootstrap.
modelclaude-haiku-4-5Model id requested from the gateway.
gatewayUrlhttps://llm.smoo.ai/v1OpenAI-compatible LLM gateway base URL.
maxIterations6Agent-loop iteration cap per turn.
maxTokens512max_tokens sent to the gateway.
routesSmooAI protocol routesOverride the WebSocket route table.

The S3 Vectors gap: SST v4 ships no native S3 Vectors component (the service went GA 2025-12). SmoothAgentApi declares the intended bucket/index names, wires them into the Lambda env, and grants s3vectors:* — but does not create the vector bucket/index as a first-class resource by default. Provision it out-of-band per the README until your AWS provider exposes aws.s3vectors.*.

📖 Helm chart (smooth-operator)

helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator
  • pgvector Postgres is external (postgres.external: true) — point database.urlSecretRef at a pgvector-enabled database (pgvector/pgvector:pg16, CloudNativePG, RDS with pgvector).
  • Secrets wire via gateway.keySecretRef / database.urlSecretRef (reference existing secrets — e.g. external-secrets-operator — in prod; inline values are dev-only).
  • WebSocket Ingress ships with long proxy timeouts + websocket annotations (nginx defaults; ALB notes in the chart README).
  • Hardened pods: non-root, read-only rootfs, dropped capabilities, seccomp RuntimeDefault.

See helm/smooth-operator/README.md for the pgvector requirement, secret wiring, Ingress notes, and ArgoCD.

📖 Smoo-powered or bring-your-own

Bring-your-own: deploy into your AWS account (SST) or your cluster (Helm/ArgoCD). Point the gateway URL at any OpenAI-compatible endpoint, bring your own pgvector Postgres or provision the S3 Vectors index yourself. You own the infra end to end.

Smoo-powered: point the gateway at https://llm.smoo.ai/v1 for unified billing + model routing, or skip the deploy entirely and let lom.smoo.ai run the smooth-operator service for you.

🧩 Part of Smoo AI {#part-of-smoo-ai}

@smooai/deploy is built and open-sourced by Smoo AI — the AI-powered business platform with AI built into every product: CRM, customer support, campaigns, field service, observability, and developer tools.

🤝 Contributing

Issues and PRs welcome. Keep deploys in CI — never deploy locally.

📄 License

MIT © Smoo AI.


Built by Smoo AI — AI built into every product.

About

Shared Smoo AI deploy primitives — reusable SST v4 constructs (API GW WebSocket + Rust Lambda + DynamoDB + S3 Vectors) and a Helm/ArgoCD chart. Consumed by smooth-operator and dogfooded by Smoo AI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

24 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

@smooai/deploy — One agent. AWS serverless or Kubernetes.

Smoo AIlicenselom.smoo.ai

TypeScript / SST v4Helm + ArgoCDverify: tsc + helm lint

Features · Install · Usage · Platform


@smooai/deploy packages the deploy primitives for a smooth-operator-style agent so you don't hand-roll them per service. The same agent ships to AWS serverless or Kubernetes off one set of conventions — you pick the runtime, not the agent.

It gives you two production-shaped paths off the same conventions:

  • AWS serverlessnew SmoothAgentApi(...): an API Gateway WebSocket + (Rust) Lambda + DynamoDB single table + S3 blob bucket + S3 Vectors wiring + gateway-key secret + IAM links, as a single parameterized SST component.
  • Kubernetes / self-host — the smooth-operator Helm chart: an axum /ws server backed by pgvector Postgres, fronted by a WebSocket-friendly Ingress, synced by ArgoCD.

Two real consumers justify the shared package: smooth-operator (the reference WebSocket agent service, uses both surfaces today) and the smooai monorepo (dogfoods the SST constructs piecemeal).

✨ Features

You want…@smooai/deploy gives you
One construct, whole serverless backendSmoothAgentApi: WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM
Composable primitivesWebSocketLambdaApi, DynamoSingleTable exported independently
A Kubernetes path toothe smooth-operator Helm chart + ArgoCD Application
No copy-paste between servicesthe smooth-operator deploy logic, extracted and parameterized
Safe-by-default podsnon-root, read-only rootfs, dropped caps, seccomp RuntimeDefault
WebSocket-aware Ingresslong proxy timeouts + websocket annotations baked into chart defaults

📦 Install

@smooai/deploy is consumed today via a path dep for local development:

// package.json
{
"dependencies": {
"@smooai/deploy": "file:../../deploy/sst"
}
}

Publishing follow-up: publish @smooai/deploy to npm (and the chart to an OCI/HTTP Helm repo) so consumers pin a version instead of a sibling-checkout path. See docs/Consuming.md.

🚀 Usage

AWS serverless — one construct in your sst.config.ts

// consumer's sst.config.ts — inside run()import{SmoothAgentApi}from'@smooai/deploy';constagent=newSmoothAgentApi('SmoothAgent',{// The cargo-lambda output dir holding `bootstrap` (provided.al2023 / arm64).artifactDir: '../../rust/target/lambda/smooai-smooth-operator-lambda',model: 'claude-haiku-4-5',});returnagent.outputs;// { api, table, blobs, vectorBucket }

One new SmoothAgentApi(...) stands up the whole serverless backend and wires the IAM links between the pieces. The smaller building blocks — WebSocketLambdaApi, DynamoSingleTable — are exported too, so you can adopt them independently.

These are SST constructs, not a deployable app. They reference SST's ambient $-globals (sst.aws.*, $interpolate, $app), so import them from inside an SST app's run().

Kubernetes — one helm install

helm upgrade --install smooth-operator helm/smooth-operator \
--namespace smooai-smooth-operator --create-namespace \
--set image.tag=0.1.0 \
--set gateway.keySecretRef.name=smooth-operator-gateway \
--set database.urlSecretRef.name=smooth-operator-db

Postgres with the pgvector extension is an external dependency (the chart does not vendor a Postgres pod). Point database.urlSecretRef at a pgvector-enabled database — see helm/smooth-operator/README.md.

Compose the smaller primitives

SmoothAgentApi is the batteries-included path. When you want to assemble your own topology, the sub-constructs are first-class:

import{WebSocketLambdaApi,DynamoSingleTable}from'@smooai/deploy';// A DynamoDB single table (OLTP + checkpoints + connection registry).consttable=DynamoSingleTable('AgentTable',{});// An API Gateway WebSocket fronting a Rust Lambda, with your own routes.const{ api }=WebSocketLambdaApi('AgentApi',{handler: '../../rust/target/lambda/my-agent-lambda',environment: {SMOOTH_AGENT_DDB_TABLE: table.name},link: [table],// Defaults to the SmooAI protocol routes; override as needed:// routes: [{ route: 'send_message', timeout: '30 seconds' }, …],});

Defaults are sensible: the WebSocket route table covers $connect, $disconnect, send_message, ping, and $default; the gateway URL defaults to https://llm.smoo.ai/v1; the model defaults to claude-haiku-4-5.

📖 Architecture — one agent, two deploy paths

%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart LR
SRC["smooth-operator<br/>Rust agent"]
subgraph aws["AWS serverless · SmoothAgentApi"]
LAM["Rust Lambda"]
STORE[("Dynamo · S3 · Vectors")]
LAM --> STORE
end
subgraph k8s["Kubernetes · Helm + ArgoCD"]
DEP["axum /ws"]
PG[("pgvector Postgres")]
DEP --> PG
end
SRC -->|lambda artifact| LAM
SRC -->|container image| DEP
LAM -.->|OpenAI-compatible| GW[("LLM gateway")]
DEP -.->|OpenAI-compatible| GW
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class SRC warm
class STORE,PG,GW teal
Loading

The same agent ships as a Lambda artifact (serverless) or a container image (k8s). Both speak the same WebSocket protocol and call the same OpenAI-compatible LLM gateway — you pick the runtime, not the agent.

📖 Verified, not vibe-coded

Infra you can't cargo test still has to be verified. This package proves correctness without a live AWS account or cluster:

  • SST constructs typecheck against real SST platform types: pnpm sst install generates .sst/platform, then tsc --noEmit validates the constructs compile against the SDK surface — catching the SST footguns (unlinked resources, ambient-global misuse) that only next build-class checks surface.
  • Helm chart is linted and rendered: helm lint + helm template validate the chart and ArgoCD Application produce valid manifests.
  • kind-cluster smoke (CI): the rendered chart is applied to an ephemeral kind cluster so the manifests actually schedule.
  • Deployed via CI, never locally — local deploys can ship unintended changes; the pipeline owns sst deploy / argocd sync.
%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart TD
U["Construct typecheck<br/>sst install → tsc"] --> C["Conformance<br/>helm lint + template"]
C --> E["kind-cluster smoke<br/>render → apply"]
E --> J["LLM-as-judge evals<br/>multi-turn, scored 0–5"]
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class U teal
class J warm
Loading

Verify locally (no AWS creds, no deploy):

# SST constructscd sst && pnpm install && pnpm sst install && npx tsc --noEmit
# Helm chart
helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator

The full quality pyramid spans repos: the engine's 408 unit tests + LLM-as-judge evals (which caught a multi-turn defect that scored 1/5 → fixed → 5/5) and the widget's live Playwright e2e sit above this package's static + smoke verification.

📖 Constructs reference

ExportWhat it is
SmoothAgentApiThe full serverless backend (WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM).
WebSocketLambdaApiAPI Gateway WebSocket fronting a Rust Lambda, with a configurable route table.
DynamoSingleTableThe single-table Dynamo schema (OLTP + checkpoints + connection registry).

SmoothAgentApi args (selected)

ArgDefaultPurpose
artifactDir(required)The cargo lambda output dir holding bootstrap.
modelclaude-haiku-4-5Model id requested from the gateway.
gatewayUrlhttps://llm.smoo.ai/v1OpenAI-compatible LLM gateway base URL.
maxIterations6Agent-loop iteration cap per turn.
maxTokens512max_tokens sent to the gateway.
routesSmooAI protocol routesOverride the WebSocket route table.

The S3 Vectors gap: SST v4 ships no native S3 Vectors component (the service went GA 2025-12). SmoothAgentApi declares the intended bucket/index names, wires them into the Lambda env, and grants s3vectors:* — but does not create the vector bucket/index as a first-class resource by default. Provision it out-of-band per the README until your AWS provider exposes aws.s3vectors.*.

📖 Helm chart (smooth-operator)

helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator
  • pgvector Postgres is external (postgres.external: true) — point database.urlSecretRef at a pgvector-enabled database (pgvector/pgvector:pg16, CloudNativePG, RDS with pgvector).
  • Secrets wire via gateway.keySecretRef / database.urlSecretRef (reference existing secrets — e.g. external-secrets-operator — in prod; inline values are dev-only).
  • WebSocket Ingress ships with long proxy timeouts + websocket annotations (nginx defaults; ALB notes in the chart README).
  • Hardened pods: non-root, read-only rootfs, dropped capabilities, seccomp RuntimeDefault.

See helm/smooth-operator/README.md for the pgvector requirement, secret wiring, Ingress notes, and ArgoCD.

📖 Smoo-powered or bring-your-own

Bring-your-own: deploy into your AWS account (SST) or your cluster (Helm/ArgoCD). Point the gateway URL at any OpenAI-compatible endpoint, bring your own pgvector Postgres or provision the S3 Vectors index yourself. You own the infra end to end.

Smoo-powered: point the gateway at https://llm.smoo.ai/v1 for unified billing + model routing, or skip the deploy entirely and let lom.smoo.ai run the smooth-operator service for you.

🧩 Part of Smoo AI {#part-of-smoo-ai}

@smooai/deploy is built and open-sourced by Smoo AI — the AI-powered business platform with AI built into every product: CRM, customer support, campaigns, field service, observability, and developer tools.

🤝 Contributing

Issues and PRs welcome. Keep deploys in CI — never deploy locally.

📄 License

MIT © Smoo AI.


Built by Smoo AI — AI built into every product.

About

Shared Smoo AI deploy primitives — reusable SST v4 constructs (API GW WebSocket + Rust Lambda + DynamoDB + S3 Vectors) and a Helm/ArgoCD chart. Consumed by smooth-operator and dogfooded by Smoo AI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

24 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

@smooai/deploy — One agent. AWS serverless or Kubernetes.

Smoo AIlicenselom.smoo.ai

TypeScript / SST v4Helm + ArgoCDverify: tsc + helm lint

Features · Install · Usage · Platform


@smooai/deploy packages the deploy primitives for a smooth-operator-style agent so you don't hand-roll them per service. The same agent ships to AWS serverless or Kubernetes off one set of conventions — you pick the runtime, not the agent.

It gives you two production-shaped paths off the same conventions:

  • AWS serverlessnew SmoothAgentApi(...): an API Gateway WebSocket + (Rust) Lambda + DynamoDB single table + S3 blob bucket + S3 Vectors wiring + gateway-key secret + IAM links, as a single parameterized SST component.
  • Kubernetes / self-host — the smooth-operator Helm chart: an axum /ws server backed by pgvector Postgres, fronted by a WebSocket-friendly Ingress, synced by ArgoCD.

Two real consumers justify the shared package: smooth-operator (the reference WebSocket agent service, uses both surfaces today) and the smooai monorepo (dogfoods the SST constructs piecemeal).

✨ Features

You want…@smooai/deploy gives you
One construct, whole serverless backendSmoothAgentApi: WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM
Composable primitivesWebSocketLambdaApi, DynamoSingleTable exported independently
A Kubernetes path toothe smooth-operator Helm chart + ArgoCD Application
No copy-paste between servicesthe smooth-operator deploy logic, extracted and parameterized
Safe-by-default podsnon-root, read-only rootfs, dropped caps, seccomp RuntimeDefault
WebSocket-aware Ingresslong proxy timeouts + websocket annotations baked into chart defaults

📦 Install

@smooai/deploy is consumed today via a path dep for local development:

// package.json
{
"dependencies": {
"@smooai/deploy": "file:../../deploy/sst"
}
}

Publishing follow-up: publish @smooai/deploy to npm (and the chart to an OCI/HTTP Helm repo) so consumers pin a version instead of a sibling-checkout path. See docs/Consuming.md.

🚀 Usage

AWS serverless — one construct in your sst.config.ts

// consumer's sst.config.ts — inside run()import{SmoothAgentApi}from'@smooai/deploy';constagent=newSmoothAgentApi('SmoothAgent',{// The cargo-lambda output dir holding `bootstrap` (provided.al2023 / arm64).artifactDir: '../../rust/target/lambda/smooai-smooth-operator-lambda',model: 'claude-haiku-4-5',});returnagent.outputs;// { api, table, blobs, vectorBucket }

One new SmoothAgentApi(...) stands up the whole serverless backend and wires the IAM links between the pieces. The smaller building blocks — WebSocketLambdaApi, DynamoSingleTable — are exported too, so you can adopt them independently.

These are SST constructs, not a deployable app. They reference SST's ambient $-globals (sst.aws.*, $interpolate, $app), so import them from inside an SST app's run().

Kubernetes — one helm install

helm upgrade --install smooth-operator helm/smooth-operator \
--namespace smooai-smooth-operator --create-namespace \
--set image.tag=0.1.0 \
--set gateway.keySecretRef.name=smooth-operator-gateway \
--set database.urlSecretRef.name=smooth-operator-db

Postgres with the pgvector extension is an external dependency (the chart does not vendor a Postgres pod). Point database.urlSecretRef at a pgvector-enabled database — see helm/smooth-operator/README.md.

Compose the smaller primitives

SmoothAgentApi is the batteries-included path. When you want to assemble your own topology, the sub-constructs are first-class:

import{WebSocketLambdaApi,DynamoSingleTable}from'@smooai/deploy';// A DynamoDB single table (OLTP + checkpoints + connection registry).consttable=DynamoSingleTable('AgentTable',{});// An API Gateway WebSocket fronting a Rust Lambda, with your own routes.const{ api }=WebSocketLambdaApi('AgentApi',{handler: '../../rust/target/lambda/my-agent-lambda',environment: {SMOOTH_AGENT_DDB_TABLE: table.name},link: [table],// Defaults to the SmooAI protocol routes; override as needed:// routes: [{ route: 'send_message', timeout: '30 seconds' }, …],});

Defaults are sensible: the WebSocket route table covers $connect, $disconnect, send_message, ping, and $default; the gateway URL defaults to https://llm.smoo.ai/v1; the model defaults to claude-haiku-4-5.

📖 Architecture — one agent, two deploy paths

%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart LR
SRC["smooth-operator<br/>Rust agent"]
subgraph aws["AWS serverless · SmoothAgentApi"]
LAM["Rust Lambda"]
STORE[("Dynamo · S3 · Vectors")]
LAM --> STORE
end
subgraph k8s["Kubernetes · Helm + ArgoCD"]
DEP["axum /ws"]
PG[("pgvector Postgres")]
DEP --> PG
end
SRC -->|lambda artifact| LAM
SRC -->|container image| DEP
LAM -.->|OpenAI-compatible| GW[("LLM gateway")]
DEP -.->|OpenAI-compatible| GW
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class SRC warm
class STORE,PG,GW teal
Loading

The same agent ships as a Lambda artifact (serverless) or a container image (k8s). Both speak the same WebSocket protocol and call the same OpenAI-compatible LLM gateway — you pick the runtime, not the agent.

📖 Verified, not vibe-coded

Infra you can't cargo test still has to be verified. This package proves correctness without a live AWS account or cluster:

  • SST constructs typecheck against real SST platform types: pnpm sst install generates .sst/platform, then tsc --noEmit validates the constructs compile against the SDK surface — catching the SST footguns (unlinked resources, ambient-global misuse) that only next build-class checks surface.
  • Helm chart is linted and rendered: helm lint + helm template validate the chart and ArgoCD Application produce valid manifests.
  • kind-cluster smoke (CI): the rendered chart is applied to an ephemeral kind cluster so the manifests actually schedule.
  • Deployed via CI, never locally — local deploys can ship unintended changes; the pipeline owns sst deploy / argocd sync.
%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart TD
U["Construct typecheck<br/>sst install → tsc"] --> C["Conformance<br/>helm lint + template"]
C --> E["kind-cluster smoke<br/>render → apply"]
E --> J["LLM-as-judge evals<br/>multi-turn, scored 0–5"]
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class U teal
class J warm
Loading

Verify locally (no AWS creds, no deploy):

# SST constructscd sst && pnpm install && pnpm sst install && npx tsc --noEmit
# Helm chart
helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator

The full quality pyramid spans repos: the engine's 408 unit tests + LLM-as-judge evals (which caught a multi-turn defect that scored 1/5 → fixed → 5/5) and the widget's live Playwright e2e sit above this package's static + smoke verification.

📖 Constructs reference

ExportWhat it is
SmoothAgentApiThe full serverless backend (WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM).
WebSocketLambdaApiAPI Gateway WebSocket fronting a Rust Lambda, with a configurable route table.
DynamoSingleTableThe single-table Dynamo schema (OLTP + checkpoints + connection registry).

SmoothAgentApi args (selected)

ArgDefaultPurpose
artifactDir(required)The cargo lambda output dir holding bootstrap.
modelclaude-haiku-4-5Model id requested from the gateway.
gatewayUrlhttps://llm.smoo.ai/v1OpenAI-compatible LLM gateway base URL.
maxIterations6Agent-loop iteration cap per turn.
maxTokens512max_tokens sent to the gateway.
routesSmooAI protocol routesOverride the WebSocket route table.

The S3 Vectors gap: SST v4 ships no native S3 Vectors component (the service went GA 2025-12). SmoothAgentApi declares the intended bucket/index names, wires them into the Lambda env, and grants s3vectors:* — but does not create the vector bucket/index as a first-class resource by default. Provision it out-of-band per the README until your AWS provider exposes aws.s3vectors.*.

📖 Helm chart (smooth-operator)

helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator
  • pgvector Postgres is external (postgres.external: true) — point database.urlSecretRef at a pgvector-enabled database (pgvector/pgvector:pg16, CloudNativePG, RDS with pgvector).
  • Secrets wire via gateway.keySecretRef / database.urlSecretRef (reference existing secrets — e.g. external-secrets-operator — in prod; inline values are dev-only).
  • WebSocket Ingress ships with long proxy timeouts + websocket annotations (nginx defaults; ALB notes in the chart README).
  • Hardened pods: non-root, read-only rootfs, dropped capabilities, seccomp RuntimeDefault.

See helm/smooth-operator/README.md for the pgvector requirement, secret wiring, Ingress notes, and ArgoCD.

📖 Smoo-powered or bring-your-own

Bring-your-own: deploy into your AWS account (SST) or your cluster (Helm/ArgoCD). Point the gateway URL at any OpenAI-compatible endpoint, bring your own pgvector Postgres or provision the S3 Vectors index yourself. You own the infra end to end.

Smoo-powered: point the gateway at https://llm.smoo.ai/v1 for unified billing + model routing, or skip the deploy entirely and let lom.smoo.ai run the smooth-operator service for you.

🧩 Part of Smoo AI {#part-of-smoo-ai}

@smooai/deploy is built and open-sourced by Smoo AI — the AI-powered business platform with AI built into every product: CRM, customer support, campaigns, field service, observability, and developer tools.

🤝 Contributing

Issues and PRs welcome. Keep deploys in CI — never deploy locally.

📄 License

MIT © Smoo AI.


Built by Smoo AI — AI built into every product.

About

Shared Smoo AI deploy primitives — reusable SST v4 constructs (API GW WebSocket + Rust Lambda + DynamoDB + S3 Vectors) and a Helm/ArgoCD chart. Consumed by smooth-operator and dogfooded by Smoo AI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

24 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

@smooai/deploy — One agent. AWS serverless or Kubernetes.

Smoo AIlicenselom.smoo.ai

TypeScript / SST v4Helm + ArgoCDverify: tsc + helm lint

Features · Install · Usage · Platform


@smooai/deploy packages the deploy primitives for a smooth-operator-style agent so you don't hand-roll them per service. The same agent ships to AWS serverless or Kubernetes off one set of conventions — you pick the runtime, not the agent.

It gives you two production-shaped paths off the same conventions:

  • AWS serverlessnew SmoothAgentApi(...): an API Gateway WebSocket + (Rust) Lambda + DynamoDB single table + S3 blob bucket + S3 Vectors wiring + gateway-key secret + IAM links, as a single parameterized SST component.
  • Kubernetes / self-host — the smooth-operator Helm chart: an axum /ws server backed by pgvector Postgres, fronted by a WebSocket-friendly Ingress, synced by ArgoCD.

Two real consumers justify the shared package: smooth-operator (the reference WebSocket agent service, uses both surfaces today) and the smooai monorepo (dogfoods the SST constructs piecemeal).

✨ Features

You want…@smooai/deploy gives you
One construct, whole serverless backendSmoothAgentApi: WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM
Composable primitivesWebSocketLambdaApi, DynamoSingleTable exported independently
A Kubernetes path toothe smooth-operator Helm chart + ArgoCD Application
No copy-paste between servicesthe smooth-operator deploy logic, extracted and parameterized
Safe-by-default podsnon-root, read-only rootfs, dropped caps, seccomp RuntimeDefault
WebSocket-aware Ingresslong proxy timeouts + websocket annotations baked into chart defaults

📦 Install

@smooai/deploy is consumed today via a path dep for local development:

// package.json
{
"dependencies": {
"@smooai/deploy": "file:../../deploy/sst"
}
}

Publishing follow-up: publish @smooai/deploy to npm (and the chart to an OCI/HTTP Helm repo) so consumers pin a version instead of a sibling-checkout path. See docs/Consuming.md.

🚀 Usage

AWS serverless — one construct in your sst.config.ts

// consumer's sst.config.ts — inside run()import{SmoothAgentApi}from'@smooai/deploy';constagent=newSmoothAgentApi('SmoothAgent',{// The cargo-lambda output dir holding `bootstrap` (provided.al2023 / arm64).artifactDir: '../../rust/target/lambda/smooai-smooth-operator-lambda',model: 'claude-haiku-4-5',});returnagent.outputs;// { api, table, blobs, vectorBucket }

One new SmoothAgentApi(...) stands up the whole serverless backend and wires the IAM links between the pieces. The smaller building blocks — WebSocketLambdaApi, DynamoSingleTable — are exported too, so you can adopt them independently.

These are SST constructs, not a deployable app. They reference SST's ambient $-globals (sst.aws.*, $interpolate, $app), so import them from inside an SST app's run().

Kubernetes — one helm install

helm upgrade --install smooth-operator helm/smooth-operator \
--namespace smooai-smooth-operator --create-namespace \
--set image.tag=0.1.0 \
--set gateway.keySecretRef.name=smooth-operator-gateway \
--set database.urlSecretRef.name=smooth-operator-db

Postgres with the pgvector extension is an external dependency (the chart does not vendor a Postgres pod). Point database.urlSecretRef at a pgvector-enabled database — see helm/smooth-operator/README.md.

Compose the smaller primitives

SmoothAgentApi is the batteries-included path. When you want to assemble your own topology, the sub-constructs are first-class:

import{WebSocketLambdaApi,DynamoSingleTable}from'@smooai/deploy';// A DynamoDB single table (OLTP + checkpoints + connection registry).consttable=DynamoSingleTable('AgentTable',{});// An API Gateway WebSocket fronting a Rust Lambda, with your own routes.const{ api }=WebSocketLambdaApi('AgentApi',{handler: '../../rust/target/lambda/my-agent-lambda',environment: {SMOOTH_AGENT_DDB_TABLE: table.name},link: [table],// Defaults to the SmooAI protocol routes; override as needed:// routes: [{ route: 'send_message', timeout: '30 seconds' }, …],});

Defaults are sensible: the WebSocket route table covers $connect, $disconnect, send_message, ping, and $default; the gateway URL defaults to https://llm.smoo.ai/v1; the model defaults to claude-haiku-4-5.

📖 Architecture — one agent, two deploy paths

%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart LR
SRC["smooth-operator<br/>Rust agent"]
subgraph aws["AWS serverless · SmoothAgentApi"]
LAM["Rust Lambda"]
STORE[("Dynamo · S3 · Vectors")]
LAM --> STORE
end
subgraph k8s["Kubernetes · Helm + ArgoCD"]
DEP["axum /ws"]
PG[("pgvector Postgres")]
DEP --> PG
end
SRC -->|lambda artifact| LAM
SRC -->|container image| DEP
LAM -.->|OpenAI-compatible| GW[("LLM gateway")]
DEP -.->|OpenAI-compatible| GW
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class SRC warm
class STORE,PG,GW teal
Loading

The same agent ships as a Lambda artifact (serverless) or a container image (k8s). Both speak the same WebSocket protocol and call the same OpenAI-compatible LLM gateway — you pick the runtime, not the agent.

📖 Verified, not vibe-coded

Infra you can't cargo test still has to be verified. This package proves correctness without a live AWS account or cluster:

  • SST constructs typecheck against real SST platform types: pnpm sst install generates .sst/platform, then tsc --noEmit validates the constructs compile against the SDK surface — catching the SST footguns (unlinked resources, ambient-global misuse) that only next build-class checks surface.
  • Helm chart is linted and rendered: helm lint + helm template validate the chart and ArgoCD Application produce valid manifests.
  • kind-cluster smoke (CI): the rendered chart is applied to an ephemeral kind cluster so the manifests actually schedule.
  • Deployed via CI, never locally — local deploys can ship unintended changes; the pipeline owns sst deploy / argocd sync.
%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart TD
U["Construct typecheck<br/>sst install → tsc"] --> C["Conformance<br/>helm lint + template"]
C --> E["kind-cluster smoke<br/>render → apply"]
E --> J["LLM-as-judge evals<br/>multi-turn, scored 0–5"]
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class U teal
class J warm
Loading

Verify locally (no AWS creds, no deploy):

# SST constructscd sst && pnpm install && pnpm sst install && npx tsc --noEmit
# Helm chart
helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator

The full quality pyramid spans repos: the engine's 408 unit tests + LLM-as-judge evals (which caught a multi-turn defect that scored 1/5 → fixed → 5/5) and the widget's live Playwright e2e sit above this package's static + smoke verification.

📖 Constructs reference

ExportWhat it is
SmoothAgentApiThe full serverless backend (WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM).
WebSocketLambdaApiAPI Gateway WebSocket fronting a Rust Lambda, with a configurable route table.
DynamoSingleTableThe single-table Dynamo schema (OLTP + checkpoints + connection registry).

SmoothAgentApi args (selected)

ArgDefaultPurpose
artifactDir(required)The cargo lambda output dir holding bootstrap.
modelclaude-haiku-4-5Model id requested from the gateway.
gatewayUrlhttps://llm.smoo.ai/v1OpenAI-compatible LLM gateway base URL.
maxIterations6Agent-loop iteration cap per turn.
maxTokens512max_tokens sent to the gateway.
routesSmooAI protocol routesOverride the WebSocket route table.

The S3 Vectors gap: SST v4 ships no native S3 Vectors component (the service went GA 2025-12). SmoothAgentApi declares the intended bucket/index names, wires them into the Lambda env, and grants s3vectors:* — but does not create the vector bucket/index as a first-class resource by default. Provision it out-of-band per the README until your AWS provider exposes aws.s3vectors.*.

📖 Helm chart (smooth-operator)

helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator
  • pgvector Postgres is external (postgres.external: true) — point database.urlSecretRef at a pgvector-enabled database (pgvector/pgvector:pg16, CloudNativePG, RDS with pgvector).
  • Secrets wire via gateway.keySecretRef / database.urlSecretRef (reference existing secrets — e.g. external-secrets-operator — in prod; inline values are dev-only).
  • WebSocket Ingress ships with long proxy timeouts + websocket annotations (nginx defaults; ALB notes in the chart README).
  • Hardened pods: non-root, read-only rootfs, dropped capabilities, seccomp RuntimeDefault.

See helm/smooth-operator/README.md for the pgvector requirement, secret wiring, Ingress notes, and ArgoCD.

📖 Smoo-powered or bring-your-own

Bring-your-own: deploy into your AWS account (SST) or your cluster (Helm/ArgoCD). Point the gateway URL at any OpenAI-compatible endpoint, bring your own pgvector Postgres or provision the S3 Vectors index yourself. You own the infra end to end.

Smoo-powered: point the gateway at https://llm.smoo.ai/v1 for unified billing + model routing, or skip the deploy entirely and let lom.smoo.ai run the smooth-operator service for you.

🧩 Part of Smoo AI {#part-of-smoo-ai}

@smooai/deploy is built and open-sourced by Smoo AI — the AI-powered business platform with AI built into every product: CRM, customer support, campaigns, field service, observability, and developer tools.

🤝 Contributing

Issues and PRs welcome. Keep deploys in CI — never deploy locally.

📄 License

MIT © Smoo AI.


Built by Smoo AI — AI built into every product.

About

Shared Smoo AI deploy primitives — reusable SST v4 constructs (API GW WebSocket + Rust Lambda + DynamoDB + S3 Vectors) and a Helm/ArgoCD chart. Consumed by smooth-operator and dogfooded by Smoo AI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

24 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

@smooai/deploy — One agent. AWS serverless or Kubernetes.

Smoo AIlicenselom.smoo.ai

TypeScript / SST v4Helm + ArgoCDverify: tsc + helm lint

Features · Install · Usage · Platform


@smooai/deploy packages the deploy primitives for a smooth-operator-style agent so you don't hand-roll them per service. The same agent ships to AWS serverless or Kubernetes off one set of conventions — you pick the runtime, not the agent.

It gives you two production-shaped paths off the same conventions:

  • AWS serverlessnew SmoothAgentApi(...): an API Gateway WebSocket + (Rust) Lambda + DynamoDB single table + S3 blob bucket + S3 Vectors wiring + gateway-key secret + IAM links, as a single parameterized SST component.
  • Kubernetes / self-host — the smooth-operator Helm chart: an axum /ws server backed by pgvector Postgres, fronted by a WebSocket-friendly Ingress, synced by ArgoCD.

Two real consumers justify the shared package: smooth-operator (the reference WebSocket agent service, uses both surfaces today) and the smooai monorepo (dogfoods the SST constructs piecemeal).

✨ Features

You want…@smooai/deploy gives you
One construct, whole serverless backendSmoothAgentApi: WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM
Composable primitivesWebSocketLambdaApi, DynamoSingleTable exported independently
A Kubernetes path toothe smooth-operator Helm chart + ArgoCD Application
No copy-paste between servicesthe smooth-operator deploy logic, extracted and parameterized
Safe-by-default podsnon-root, read-only rootfs, dropped caps, seccomp RuntimeDefault
WebSocket-aware Ingresslong proxy timeouts + websocket annotations baked into chart defaults

📦 Install

@smooai/deploy is consumed today via a path dep for local development:

// package.json
{
"dependencies": {
"@smooai/deploy": "file:../../deploy/sst"
}
}

Publishing follow-up: publish @smooai/deploy to npm (and the chart to an OCI/HTTP Helm repo) so consumers pin a version instead of a sibling-checkout path. See docs/Consuming.md.

🚀 Usage

AWS serverless — one construct in your sst.config.ts

// consumer's sst.config.ts — inside run()import{SmoothAgentApi}from'@smooai/deploy';constagent=newSmoothAgentApi('SmoothAgent',{// The cargo-lambda output dir holding `bootstrap` (provided.al2023 / arm64).artifactDir: '../../rust/target/lambda/smooai-smooth-operator-lambda',model: 'claude-haiku-4-5',});returnagent.outputs;// { api, table, blobs, vectorBucket }

One new SmoothAgentApi(...) stands up the whole serverless backend and wires the IAM links between the pieces. The smaller building blocks — WebSocketLambdaApi, DynamoSingleTable — are exported too, so you can adopt them independently.

These are SST constructs, not a deployable app. They reference SST's ambient $-globals (sst.aws.*, $interpolate, $app), so import them from inside an SST app's run().

Kubernetes — one helm install

helm upgrade --install smooth-operator helm/smooth-operator \
--namespace smooai-smooth-operator --create-namespace \
--set image.tag=0.1.0 \
--set gateway.keySecretRef.name=smooth-operator-gateway \
--set database.urlSecretRef.name=smooth-operator-db

Postgres with the pgvector extension is an external dependency (the chart does not vendor a Postgres pod). Point database.urlSecretRef at a pgvector-enabled database — see helm/smooth-operator/README.md.

Compose the smaller primitives

SmoothAgentApi is the batteries-included path. When you want to assemble your own topology, the sub-constructs are first-class:

import{WebSocketLambdaApi,DynamoSingleTable}from'@smooai/deploy';// A DynamoDB single table (OLTP + checkpoints + connection registry).consttable=DynamoSingleTable('AgentTable',{});// An API Gateway WebSocket fronting a Rust Lambda, with your own routes.const{ api }=WebSocketLambdaApi('AgentApi',{handler: '../../rust/target/lambda/my-agent-lambda',environment: {SMOOTH_AGENT_DDB_TABLE: table.name},link: [table],// Defaults to the SmooAI protocol routes; override as needed:// routes: [{ route: 'send_message', timeout: '30 seconds' }, …],});

Defaults are sensible: the WebSocket route table covers $connect, $disconnect, send_message, ping, and $default; the gateway URL defaults to https://llm.smoo.ai/v1; the model defaults to claude-haiku-4-5.

📖 Architecture — one agent, two deploy paths

%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart LR
SRC["smooth-operator<br/>Rust agent"]
subgraph aws["AWS serverless · SmoothAgentApi"]
LAM["Rust Lambda"]
STORE[("Dynamo · S3 · Vectors")]
LAM --> STORE
end
subgraph k8s["Kubernetes · Helm + ArgoCD"]
DEP["axum /ws"]
PG[("pgvector Postgres")]
DEP --> PG
end
SRC -->|lambda artifact| LAM
SRC -->|container image| DEP
LAM -.->|OpenAI-compatible| GW[("LLM gateway")]
DEP -.->|OpenAI-compatible| GW
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class SRC warm
class STORE,PG,GW teal
Loading

The same agent ships as a Lambda artifact (serverless) or a container image (k8s). Both speak the same WebSocket protocol and call the same OpenAI-compatible LLM gateway — you pick the runtime, not the agent.

📖 Verified, not vibe-coded

Infra you can't cargo test still has to be verified. This package proves correctness without a live AWS account or cluster:

  • SST constructs typecheck against real SST platform types: pnpm sst install generates .sst/platform, then tsc --noEmit validates the constructs compile against the SDK surface — catching the SST footguns (unlinked resources, ambient-global misuse) that only next build-class checks surface.
  • Helm chart is linted and rendered: helm lint + helm template validate the chart and ArgoCD Application produce valid manifests.
  • kind-cluster smoke (CI): the rendered chart is applied to an ephemeral kind cluster so the manifests actually schedule.
  • Deployed via CI, never locally — local deploys can ship unintended changes; the pipeline owns sst deploy / argocd sync.
%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart TD
U["Construct typecheck<br/>sst install → tsc"] --> C["Conformance<br/>helm lint + template"]
C --> E["kind-cluster smoke<br/>render → apply"]
E --> J["LLM-as-judge evals<br/>multi-turn, scored 0–5"]
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class U teal
class J warm
Loading

Verify locally (no AWS creds, no deploy):

# SST constructscd sst && pnpm install && pnpm sst install && npx tsc --noEmit
# Helm chart
helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator

The full quality pyramid spans repos: the engine's 408 unit tests + LLM-as-judge evals (which caught a multi-turn defect that scored 1/5 → fixed → 5/5) and the widget's live Playwright e2e sit above this package's static + smoke verification.

📖 Constructs reference

ExportWhat it is
SmoothAgentApiThe full serverless backend (WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM).
WebSocketLambdaApiAPI Gateway WebSocket fronting a Rust Lambda, with a configurable route table.
DynamoSingleTableThe single-table Dynamo schema (OLTP + checkpoints + connection registry).

SmoothAgentApi args (selected)

ArgDefaultPurpose
artifactDir(required)The cargo lambda output dir holding bootstrap.
modelclaude-haiku-4-5Model id requested from the gateway.
gatewayUrlhttps://llm.smoo.ai/v1OpenAI-compatible LLM gateway base URL.
maxIterations6Agent-loop iteration cap per turn.
maxTokens512max_tokens sent to the gateway.
routesSmooAI protocol routesOverride the WebSocket route table.

The S3 Vectors gap: SST v4 ships no native S3 Vectors component (the service went GA 2025-12). SmoothAgentApi declares the intended bucket/index names, wires them into the Lambda env, and grants s3vectors:* — but does not create the vector bucket/index as a first-class resource by default. Provision it out-of-band per the README until your AWS provider exposes aws.s3vectors.*.

📖 Helm chart (smooth-operator)

helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator
  • pgvector Postgres is external (postgres.external: true) — point database.urlSecretRef at a pgvector-enabled database (pgvector/pgvector:pg16, CloudNativePG, RDS with pgvector).
  • Secrets wire via gateway.keySecretRef / database.urlSecretRef (reference existing secrets — e.g. external-secrets-operator — in prod; inline values are dev-only).
  • WebSocket Ingress ships with long proxy timeouts + websocket annotations (nginx defaults; ALB notes in the chart README).
  • Hardened pods: non-root, read-only rootfs, dropped capabilities, seccomp RuntimeDefault.

See helm/smooth-operator/README.md for the pgvector requirement, secret wiring, Ingress notes, and ArgoCD.

📖 Smoo-powered or bring-your-own

Bring-your-own: deploy into your AWS account (SST) or your cluster (Helm/ArgoCD). Point the gateway URL at any OpenAI-compatible endpoint, bring your own pgvector Postgres or provision the S3 Vectors index yourself. You own the infra end to end.

Smoo-powered: point the gateway at https://llm.smoo.ai/v1 for unified billing + model routing, or skip the deploy entirely and let lom.smoo.ai run the smooth-operator service for you.

🧩 Part of Smoo AI {#part-of-smoo-ai}

@smooai/deploy is built and open-sourced by Smoo AI — the AI-powered business platform with AI built into every product: CRM, customer support, campaigns, field service, observability, and developer tools.

🤝 Contributing

Issues and PRs welcome. Keep deploys in CI — never deploy locally.

📄 License

MIT © Smoo AI.


Built by Smoo AI — AI built into every product.

About

Shared Smoo AI deploy primitives — reusable SST v4 constructs (API GW WebSocket + Rust Lambda + DynamoDB + S3 Vectors) and a Helm/ArgoCD chart. Consumed by smooth-operator and dogfooded by Smoo AI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

24 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

@smooai/deploy — One agent. AWS serverless or Kubernetes.

Smoo AIlicenselom.smoo.ai

TypeScript / SST v4Helm + ArgoCDverify: tsc + helm lint

Features · Install · Usage · Platform


@smooai/deploy packages the deploy primitives for a smooth-operator-style agent so you don't hand-roll them per service. The same agent ships to AWS serverless or Kubernetes off one set of conventions — you pick the runtime, not the agent.

It gives you two production-shaped paths off the same conventions:

  • AWS serverlessnew SmoothAgentApi(...): an API Gateway WebSocket + (Rust) Lambda + DynamoDB single table + S3 blob bucket + S3 Vectors wiring + gateway-key secret + IAM links, as a single parameterized SST component.
  • Kubernetes / self-host — the smooth-operator Helm chart: an axum /ws server backed by pgvector Postgres, fronted by a WebSocket-friendly Ingress, synced by ArgoCD.

Two real consumers justify the shared package: smooth-operator (the reference WebSocket agent service, uses both surfaces today) and the smooai monorepo (dogfoods the SST constructs piecemeal).

✨ Features

You want…@smooai/deploy gives you
One construct, whole serverless backendSmoothAgentApi: WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM
Composable primitivesWebSocketLambdaApi, DynamoSingleTable exported independently
A Kubernetes path toothe smooth-operator Helm chart + ArgoCD Application
No copy-paste between servicesthe smooth-operator deploy logic, extracted and parameterized
Safe-by-default podsnon-root, read-only rootfs, dropped caps, seccomp RuntimeDefault
WebSocket-aware Ingresslong proxy timeouts + websocket annotations baked into chart defaults

📦 Install

@smooai/deploy is consumed today via a path dep for local development:

// package.json
{
"dependencies": {
"@smooai/deploy": "file:../../deploy/sst"
}
}

Publishing follow-up: publish @smooai/deploy to npm (and the chart to an OCI/HTTP Helm repo) so consumers pin a version instead of a sibling-checkout path. See docs/Consuming.md.

🚀 Usage

AWS serverless — one construct in your sst.config.ts

// consumer's sst.config.ts — inside run()import{SmoothAgentApi}from'@smooai/deploy';constagent=newSmoothAgentApi('SmoothAgent',{// The cargo-lambda output dir holding `bootstrap` (provided.al2023 / arm64).artifactDir: '../../rust/target/lambda/smooai-smooth-operator-lambda',model: 'claude-haiku-4-5',});returnagent.outputs;// { api, table, blobs, vectorBucket }

One new SmoothAgentApi(...) stands up the whole serverless backend and wires the IAM links between the pieces. The smaller building blocks — WebSocketLambdaApi, DynamoSingleTable — are exported too, so you can adopt them independently.

These are SST constructs, not a deployable app. They reference SST's ambient $-globals (sst.aws.*, $interpolate, $app), so import them from inside an SST app's run().

Kubernetes — one helm install

helm upgrade --install smooth-operator helm/smooth-operator \
--namespace smooai-smooth-operator --create-namespace \
--set image.tag=0.1.0 \
--set gateway.keySecretRef.name=smooth-operator-gateway \
--set database.urlSecretRef.name=smooth-operator-db

Postgres with the pgvector extension is an external dependency (the chart does not vendor a Postgres pod). Point database.urlSecretRef at a pgvector-enabled database — see helm/smooth-operator/README.md.

Compose the smaller primitives

SmoothAgentApi is the batteries-included path. When you want to assemble your own topology, the sub-constructs are first-class:

import{WebSocketLambdaApi,DynamoSingleTable}from'@smooai/deploy';// A DynamoDB single table (OLTP + checkpoints + connection registry).consttable=DynamoSingleTable('AgentTable',{});// An API Gateway WebSocket fronting a Rust Lambda, with your own routes.const{ api }=WebSocketLambdaApi('AgentApi',{handler: '../../rust/target/lambda/my-agent-lambda',environment: {SMOOTH_AGENT_DDB_TABLE: table.name},link: [table],// Defaults to the SmooAI protocol routes; override as needed:// routes: [{ route: 'send_message', timeout: '30 seconds' }, …],});

Defaults are sensible: the WebSocket route table covers $connect, $disconnect, send_message, ping, and $default; the gateway URL defaults to https://llm.smoo.ai/v1; the model defaults to claude-haiku-4-5.

📖 Architecture — one agent, two deploy paths

%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart LR
SRC["smooth-operator<br/>Rust agent"]
subgraph aws["AWS serverless · SmoothAgentApi"]
LAM["Rust Lambda"]
STORE[("Dynamo · S3 · Vectors")]
LAM --> STORE
end
subgraph k8s["Kubernetes · Helm + ArgoCD"]
DEP["axum /ws"]
PG[("pgvector Postgres")]
DEP --> PG
end
SRC -->|lambda artifact| LAM
SRC -->|container image| DEP
LAM -.->|OpenAI-compatible| GW[("LLM gateway")]
DEP -.->|OpenAI-compatible| GW
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class SRC warm
class STORE,PG,GW teal
Loading

The same agent ships as a Lambda artifact (serverless) or a container image (k8s). Both speak the same WebSocket protocol and call the same OpenAI-compatible LLM gateway — you pick the runtime, not the agent.

📖 Verified, not vibe-coded

Infra you can't cargo test still has to be verified. This package proves correctness without a live AWS account or cluster:

  • SST constructs typecheck against real SST platform types: pnpm sst install generates .sst/platform, then tsc --noEmit validates the constructs compile against the SDK surface — catching the SST footguns (unlinked resources, ambient-global misuse) that only next build-class checks surface.
  • Helm chart is linted and rendered: helm lint + helm template validate the chart and ArgoCD Application produce valid manifests.
  • kind-cluster smoke (CI): the rendered chart is applied to an ephemeral kind cluster so the manifests actually schedule.
  • Deployed via CI, never locally — local deploys can ship unintended changes; the pipeline owns sst deploy / argocd sync.
%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart TD
U["Construct typecheck<br/>sst install → tsc"] --> C["Conformance<br/>helm lint + template"]
C --> E["kind-cluster smoke<br/>render → apply"]
E --> J["LLM-as-judge evals<br/>multi-turn, scored 0–5"]
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class U teal
class J warm
Loading

Verify locally (no AWS creds, no deploy):

# SST constructscd sst && pnpm install && pnpm sst install && npx tsc --noEmit
# Helm chart
helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator

The full quality pyramid spans repos: the engine's 408 unit tests + LLM-as-judge evals (which caught a multi-turn defect that scored 1/5 → fixed → 5/5) and the widget's live Playwright e2e sit above this package's static + smoke verification.

📖 Constructs reference

ExportWhat it is
SmoothAgentApiThe full serverless backend (WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM).
WebSocketLambdaApiAPI Gateway WebSocket fronting a Rust Lambda, with a configurable route table.
DynamoSingleTableThe single-table Dynamo schema (OLTP + checkpoints + connection registry).

SmoothAgentApi args (selected)

ArgDefaultPurpose
artifactDir(required)The cargo lambda output dir holding bootstrap.
modelclaude-haiku-4-5Model id requested from the gateway.
gatewayUrlhttps://llm.smoo.ai/v1OpenAI-compatible LLM gateway base URL.
maxIterations6Agent-loop iteration cap per turn.
maxTokens512max_tokens sent to the gateway.
routesSmooAI protocol routesOverride the WebSocket route table.

The S3 Vectors gap: SST v4 ships no native S3 Vectors component (the service went GA 2025-12). SmoothAgentApi declares the intended bucket/index names, wires them into the Lambda env, and grants s3vectors:* — but does not create the vector bucket/index as a first-class resource by default. Provision it out-of-band per the README until your AWS provider exposes aws.s3vectors.*.

📖 Helm chart (smooth-operator)

helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator
  • pgvector Postgres is external (postgres.external: true) — point database.urlSecretRef at a pgvector-enabled database (pgvector/pgvector:pg16, CloudNativePG, RDS with pgvector).
  • Secrets wire via gateway.keySecretRef / database.urlSecretRef (reference existing secrets — e.g. external-secrets-operator — in prod; inline values are dev-only).
  • WebSocket Ingress ships with long proxy timeouts + websocket annotations (nginx defaults; ALB notes in the chart README).
  • Hardened pods: non-root, read-only rootfs, dropped capabilities, seccomp RuntimeDefault.

See helm/smooth-operator/README.md for the pgvector requirement, secret wiring, Ingress notes, and ArgoCD.

📖 Smoo-powered or bring-your-own

Bring-your-own: deploy into your AWS account (SST) or your cluster (Helm/ArgoCD). Point the gateway URL at any OpenAI-compatible endpoint, bring your own pgvector Postgres or provision the S3 Vectors index yourself. You own the infra end to end.

Smoo-powered: point the gateway at https://llm.smoo.ai/v1 for unified billing + model routing, or skip the deploy entirely and let lom.smoo.ai run the smooth-operator service for you.

🧩 Part of Smoo AI {#part-of-smoo-ai}

@smooai/deploy is built and open-sourced by Smoo AI — the AI-powered business platform with AI built into every product: CRM, customer support, campaigns, field service, observability, and developer tools.

🤝 Contributing

Issues and PRs welcome. Keep deploys in CI — never deploy locally.

📄 License

MIT © Smoo AI.


Built by Smoo AI — AI built into every product.

About

Shared Smoo AI deploy primitives — reusable SST v4 constructs (API GW WebSocket + Rust Lambda + DynamoDB + S3 Vectors) and a Helm/ArgoCD chart. Consumed by smooth-operator and dogfooded by Smoo AI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

24 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

@smooai/deploy — One agent. AWS serverless or Kubernetes.

Smoo AIlicenselom.smoo.ai

TypeScript / SST v4Helm + ArgoCDverify: tsc + helm lint

Features · Install · Usage · Platform


@smooai/deploy packages the deploy primitives for a smooth-operator-style agent so you don't hand-roll them per service. The same agent ships to AWS serverless or Kubernetes off one set of conventions — you pick the runtime, not the agent.

It gives you two production-shaped paths off the same conventions:

  • AWS serverlessnew SmoothAgentApi(...): an API Gateway WebSocket + (Rust) Lambda + DynamoDB single table + S3 blob bucket + S3 Vectors wiring + gateway-key secret + IAM links, as a single parameterized SST component.
  • Kubernetes / self-host — the smooth-operator Helm chart: an axum /ws server backed by pgvector Postgres, fronted by a WebSocket-friendly Ingress, synced by ArgoCD.

Two real consumers justify the shared package: smooth-operator (the reference WebSocket agent service, uses both surfaces today) and the smooai monorepo (dogfoods the SST constructs piecemeal).

✨ Features

You want…@smooai/deploy gives you
One construct, whole serverless backendSmoothAgentApi: WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM
Composable primitivesWebSocketLambdaApi, DynamoSingleTable exported independently
A Kubernetes path toothe smooth-operator Helm chart + ArgoCD Application
No copy-paste between servicesthe smooth-operator deploy logic, extracted and parameterized
Safe-by-default podsnon-root, read-only rootfs, dropped caps, seccomp RuntimeDefault
WebSocket-aware Ingresslong proxy timeouts + websocket annotations baked into chart defaults

📦 Install

@smooai/deploy is consumed today via a path dep for local development:

// package.json
{
"dependencies": {
"@smooai/deploy": "file:../../deploy/sst"
}
}

Publishing follow-up: publish @smooai/deploy to npm (and the chart to an OCI/HTTP Helm repo) so consumers pin a version instead of a sibling-checkout path. See docs/Consuming.md.

🚀 Usage

AWS serverless — one construct in your sst.config.ts

// consumer's sst.config.ts — inside run()import{SmoothAgentApi}from'@smooai/deploy';constagent=newSmoothAgentApi('SmoothAgent',{// The cargo-lambda output dir holding `bootstrap` (provided.al2023 / arm64).artifactDir: '../../rust/target/lambda/smooai-smooth-operator-lambda',model: 'claude-haiku-4-5',});returnagent.outputs;// { api, table, blobs, vectorBucket }

One new SmoothAgentApi(...) stands up the whole serverless backend and wires the IAM links between the pieces. The smaller building blocks — WebSocketLambdaApi, DynamoSingleTable — are exported too, so you can adopt them independently.

These are SST constructs, not a deployable app. They reference SST's ambient $-globals (sst.aws.*, $interpolate, $app), so import them from inside an SST app's run().

Kubernetes — one helm install

helm upgrade --install smooth-operator helm/smooth-operator \
--namespace smooai-smooth-operator --create-namespace \
--set image.tag=0.1.0 \
--set gateway.keySecretRef.name=smooth-operator-gateway \
--set database.urlSecretRef.name=smooth-operator-db

Postgres with the pgvector extension is an external dependency (the chart does not vendor a Postgres pod). Point database.urlSecretRef at a pgvector-enabled database — see helm/smooth-operator/README.md.

Compose the smaller primitives

SmoothAgentApi is the batteries-included path. When you want to assemble your own topology, the sub-constructs are first-class:

import{WebSocketLambdaApi,DynamoSingleTable}from'@smooai/deploy';// A DynamoDB single table (OLTP + checkpoints + connection registry).consttable=DynamoSingleTable('AgentTable',{});// An API Gateway WebSocket fronting a Rust Lambda, with your own routes.const{ api }=WebSocketLambdaApi('AgentApi',{handler: '../../rust/target/lambda/my-agent-lambda',environment: {SMOOTH_AGENT_DDB_TABLE: table.name},link: [table],// Defaults to the SmooAI protocol routes; override as needed:// routes: [{ route: 'send_message', timeout: '30 seconds' }, …],});

Defaults are sensible: the WebSocket route table covers $connect, $disconnect, send_message, ping, and $default; the gateway URL defaults to https://llm.smoo.ai/v1; the model defaults to claude-haiku-4-5.

📖 Architecture — one agent, two deploy paths

%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart LR
SRC["smooth-operator<br/>Rust agent"]
subgraph aws["AWS serverless · SmoothAgentApi"]
LAM["Rust Lambda"]
STORE[("Dynamo · S3 · Vectors")]
LAM --> STORE
end
subgraph k8s["Kubernetes · Helm + ArgoCD"]
DEP["axum /ws"]
PG[("pgvector Postgres")]
DEP --> PG
end
SRC -->|lambda artifact| LAM
SRC -->|container image| DEP
LAM -.->|OpenAI-compatible| GW[("LLM gateway")]
DEP -.->|OpenAI-compatible| GW
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class SRC warm
class STORE,PG,GW teal
Loading

The same agent ships as a Lambda artifact (serverless) or a container image (k8s). Both speak the same WebSocket protocol and call the same OpenAI-compatible LLM gateway — you pick the runtime, not the agent.

📖 Verified, not vibe-coded

Infra you can't cargo test still has to be verified. This package proves correctness without a live AWS account or cluster:

  • SST constructs typecheck against real SST platform types: pnpm sst install generates .sst/platform, then tsc --noEmit validates the constructs compile against the SDK surface — catching the SST footguns (unlinked resources, ambient-global misuse) that only next build-class checks surface.
  • Helm chart is linted and rendered: helm lint + helm template validate the chart and ArgoCD Application produce valid manifests.
  • kind-cluster smoke (CI): the rendered chart is applied to an ephemeral kind cluster so the manifests actually schedule.
  • Deployed via CI, never locally — local deploys can ship unintended changes; the pipeline owns sst deploy / argocd sync.
%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart TD
U["Construct typecheck<br/>sst install → tsc"] --> C["Conformance<br/>helm lint + template"]
C --> E["kind-cluster smoke<br/>render → apply"]
E --> J["LLM-as-judge evals<br/>multi-turn, scored 0–5"]
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class U teal
class J warm
Loading

Verify locally (no AWS creds, no deploy):

# SST constructscd sst && pnpm install && pnpm sst install && npx tsc --noEmit
# Helm chart
helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator

The full quality pyramid spans repos: the engine's 408 unit tests + LLM-as-judge evals (which caught a multi-turn defect that scored 1/5 → fixed → 5/5) and the widget's live Playwright e2e sit above this package's static + smoke verification.

📖 Constructs reference

ExportWhat it is
SmoothAgentApiThe full serverless backend (WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM).
WebSocketLambdaApiAPI Gateway WebSocket fronting a Rust Lambda, with a configurable route table.
DynamoSingleTableThe single-table Dynamo schema (OLTP + checkpoints + connection registry).

SmoothAgentApi args (selected)

ArgDefaultPurpose
artifactDir(required)The cargo lambda output dir holding bootstrap.
modelclaude-haiku-4-5Model id requested from the gateway.
gatewayUrlhttps://llm.smoo.ai/v1OpenAI-compatible LLM gateway base URL.
maxIterations6Agent-loop iteration cap per turn.
maxTokens512max_tokens sent to the gateway.
routesSmooAI protocol routesOverride the WebSocket route table.

The S3 Vectors gap: SST v4 ships no native S3 Vectors component (the service went GA 2025-12). SmoothAgentApi declares the intended bucket/index names, wires them into the Lambda env, and grants s3vectors:* — but does not create the vector bucket/index as a first-class resource by default. Provision it out-of-band per the README until your AWS provider exposes aws.s3vectors.*.

📖 Helm chart (smooth-operator)

helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator
  • pgvector Postgres is external (postgres.external: true) — point database.urlSecretRef at a pgvector-enabled database (pgvector/pgvector:pg16, CloudNativePG, RDS with pgvector).
  • Secrets wire via gateway.keySecretRef / database.urlSecretRef (reference existing secrets — e.g. external-secrets-operator — in prod; inline values are dev-only).
  • WebSocket Ingress ships with long proxy timeouts + websocket annotations (nginx defaults; ALB notes in the chart README).
  • Hardened pods: non-root, read-only rootfs, dropped capabilities, seccomp RuntimeDefault.

See helm/smooth-operator/README.md for the pgvector requirement, secret wiring, Ingress notes, and ArgoCD.

📖 Smoo-powered or bring-your-own

Bring-your-own: deploy into your AWS account (SST) or your cluster (Helm/ArgoCD). Point the gateway URL at any OpenAI-compatible endpoint, bring your own pgvector Postgres or provision the S3 Vectors index yourself. You own the infra end to end.

Smoo-powered: point the gateway at https://llm.smoo.ai/v1 for unified billing + model routing, or skip the deploy entirely and let lom.smoo.ai run the smooth-operator service for you.

🧩 Part of Smoo AI {#part-of-smoo-ai}

@smooai/deploy is built and open-sourced by Smoo AI — the AI-powered business platform with AI built into every product: CRM, customer support, campaigns, field service, observability, and developer tools.

🤝 Contributing

Issues and PRs welcome. Keep deploys in CI — never deploy locally.

📄 License

MIT © Smoo AI.


Built by Smoo AI — AI built into every product.

About

Shared Smoo AI deploy primitives — reusable SST v4 constructs (API GW WebSocket + Rust Lambda + DynamoDB + S3 Vectors) and a Helm/ArgoCD chart. Consumed by smooth-operator and dogfooded by Smoo AI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

24 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

@smooai/deploy — One agent. AWS serverless or Kubernetes.

Smoo AIlicenselom.smoo.ai

TypeScript / SST v4Helm + ArgoCDverify: tsc + helm lint

Features · Install · Usage · Platform


@smooai/deploy packages the deploy primitives for a smooth-operator-style agent so you don't hand-roll them per service. The same agent ships to AWS serverless or Kubernetes off one set of conventions — you pick the runtime, not the agent.

It gives you two production-shaped paths off the same conventions:

  • AWS serverlessnew SmoothAgentApi(...): an API Gateway WebSocket + (Rust) Lambda + DynamoDB single table + S3 blob bucket + S3 Vectors wiring + gateway-key secret + IAM links, as a single parameterized SST component.
  • Kubernetes / self-host — the smooth-operator Helm chart: an axum /ws server backed by pgvector Postgres, fronted by a WebSocket-friendly Ingress, synced by ArgoCD.

Two real consumers justify the shared package: smooth-operator (the reference WebSocket agent service, uses both surfaces today) and the smooai monorepo (dogfoods the SST constructs piecemeal).

✨ Features

You want…@smooai/deploy gives you
One construct, whole serverless backendSmoothAgentApi: WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM
Composable primitivesWebSocketLambdaApi, DynamoSingleTable exported independently
A Kubernetes path toothe smooth-operator Helm chart + ArgoCD Application
No copy-paste between servicesthe smooth-operator deploy logic, extracted and parameterized
Safe-by-default podsnon-root, read-only rootfs, dropped caps, seccomp RuntimeDefault
WebSocket-aware Ingresslong proxy timeouts + websocket annotations baked into chart defaults

📦 Install

@smooai/deploy is consumed today via a path dep for local development:

// package.json
{
"dependencies": {
"@smooai/deploy": "file:../../deploy/sst"
}
}

Publishing follow-up: publish @smooai/deploy to npm (and the chart to an OCI/HTTP Helm repo) so consumers pin a version instead of a sibling-checkout path. See docs/Consuming.md.

🚀 Usage

AWS serverless — one construct in your sst.config.ts

// consumer's sst.config.ts — inside run()import{SmoothAgentApi}from'@smooai/deploy';constagent=newSmoothAgentApi('SmoothAgent',{// The cargo-lambda output dir holding `bootstrap` (provided.al2023 / arm64).artifactDir: '../../rust/target/lambda/smooai-smooth-operator-lambda',model: 'claude-haiku-4-5',});returnagent.outputs;// { api, table, blobs, vectorBucket }

One new SmoothAgentApi(...) stands up the whole serverless backend and wires the IAM links between the pieces. The smaller building blocks — WebSocketLambdaApi, DynamoSingleTable — are exported too, so you can adopt them independently.

These are SST constructs, not a deployable app. They reference SST's ambient $-globals (sst.aws.*, $interpolate, $app), so import them from inside an SST app's run().

Kubernetes — one helm install

helm upgrade --install smooth-operator helm/smooth-operator \
--namespace smooai-smooth-operator --create-namespace \
--set image.tag=0.1.0 \
--set gateway.keySecretRef.name=smooth-operator-gateway \
--set database.urlSecretRef.name=smooth-operator-db

Postgres with the pgvector extension is an external dependency (the chart does not vendor a Postgres pod). Point database.urlSecretRef at a pgvector-enabled database — see helm/smooth-operator/README.md.

Compose the smaller primitives

SmoothAgentApi is the batteries-included path. When you want to assemble your own topology, the sub-constructs are first-class:

import{WebSocketLambdaApi,DynamoSingleTable}from'@smooai/deploy';// A DynamoDB single table (OLTP + checkpoints + connection registry).consttable=DynamoSingleTable('AgentTable',{});// An API Gateway WebSocket fronting a Rust Lambda, with your own routes.const{ api }=WebSocketLambdaApi('AgentApi',{handler: '../../rust/target/lambda/my-agent-lambda',environment: {SMOOTH_AGENT_DDB_TABLE: table.name},link: [table],// Defaults to the SmooAI protocol routes; override as needed:// routes: [{ route: 'send_message', timeout: '30 seconds' }, …],});

Defaults are sensible: the WebSocket route table covers $connect, $disconnect, send_message, ping, and $default; the gateway URL defaults to https://llm.smoo.ai/v1; the model defaults to claude-haiku-4-5.

📖 Architecture — one agent, two deploy paths

%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart LR
SRC["smooth-operator<br/>Rust agent"]
subgraph aws["AWS serverless · SmoothAgentApi"]
LAM["Rust Lambda"]
STORE[("Dynamo · S3 · Vectors")]
LAM --> STORE
end
subgraph k8s["Kubernetes · Helm + ArgoCD"]
DEP["axum /ws"]
PG[("pgvector Postgres")]
DEP --> PG
end
SRC -->|lambda artifact| LAM
SRC -->|container image| DEP
LAM -.->|OpenAI-compatible| GW[("LLM gateway")]
DEP -.->|OpenAI-compatible| GW
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class SRC warm
class STORE,PG,GW teal
Loading

The same agent ships as a Lambda artifact (serverless) or a container image (k8s). Both speak the same WebSocket protocol and call the same OpenAI-compatible LLM gateway — you pick the runtime, not the agent.

📖 Verified, not vibe-coded

Infra you can't cargo test still has to be verified. This package proves correctness without a live AWS account or cluster:

  • SST constructs typecheck against real SST platform types: pnpm sst install generates .sst/platform, then tsc --noEmit validates the constructs compile against the SDK surface — catching the SST footguns (unlinked resources, ambient-global misuse) that only next build-class checks surface.
  • Helm chart is linted and rendered: helm lint + helm template validate the chart and ArgoCD Application produce valid manifests.
  • kind-cluster smoke (CI): the rendered chart is applied to an ephemeral kind cluster so the manifests actually schedule.
  • Deployed via CI, never locally — local deploys can ship unintended changes; the pipeline owns sst deploy / argocd sync.
%%{init: {'theme':'base','themeVariables':{
'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart TD
U["Construct typecheck<br/>sst install → tsc"] --> C["Conformance<br/>helm lint + template"]
C --> E["kind-cluster smoke<br/>render → apply"]
E --> J["LLM-as-judge evals<br/>multi-turn, scored 0–5"]
classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
class U teal
class J warm
Loading

Verify locally (no AWS creds, no deploy):

# SST constructscd sst && pnpm install && pnpm sst install && npx tsc --noEmit
# Helm chart
helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator

The full quality pyramid spans repos: the engine's 408 unit tests + LLM-as-judge evals (which caught a multi-turn defect that scored 1/5 → fixed → 5/5) and the widget's live Playwright e2e sit above this package's static + smoke verification.

📖 Constructs reference

ExportWhat it is
SmoothAgentApiThe full serverless backend (WS API + Lambda + Dynamo + S3 + Vectors + secret + IAM).
WebSocketLambdaApiAPI Gateway WebSocket fronting a Rust Lambda, with a configurable route table.
DynamoSingleTableThe single-table Dynamo schema (OLTP + checkpoints + connection registry).

SmoothAgentApi args (selected)

ArgDefaultPurpose
artifactDir(required)The cargo lambda output dir holding bootstrap.
modelclaude-haiku-4-5Model id requested from the gateway.
gatewayUrlhttps://llm.smoo.ai/v1OpenAI-compatible LLM gateway base URL.
maxIterations6Agent-loop iteration cap per turn.
maxTokens512max_tokens sent to the gateway.
routesSmooAI protocol routesOverride the WebSocket route table.

The S3 Vectors gap: SST v4 ships no native S3 Vectors component (the service went GA 2025-12). SmoothAgentApi declares the intended bucket/index names, wires them into the Lambda env, and grants s3vectors:* — but does not create the vector bucket/index as a first-class resource by default. Provision it out-of-band per the README until your AWS provider exposes aws.s3vectors.*.

📖 Helm chart (smooth-operator)

helm lint helm/smooth-operator
helm template smooth-operator helm/smooth-operator
  • pgvector Postgres is external (postgres.external: true) — point database.urlSecretRef at a pgvector-enabled database (pgvector/pgvector:pg16, CloudNativePG, RDS with pgvector).
  • Secrets wire via gateway.keySecretRef / database.urlSecretRef (reference existing secrets — e.g. external-secrets-operator — in prod; inline values are dev-only).
  • WebSocket Ingress ships with long proxy timeouts + websocket annotations (nginx defaults; ALB notes in the chart README).
  • Hardened pods: non-root, read-only rootfs, dropped capabilities, seccomp RuntimeDefault.

See helm/smooth-operator/README.md for the pgvector requirement, secret wiring, Ingress notes, and ArgoCD.

📖 Smoo-powered or bring-your-own

Bring-your-own: deploy into your AWS account (SST) or your cluster (Helm/ArgoCD). Point the gateway URL at any OpenAI-compatible endpoint, bring your own pgvector Postgres or provision the S3 Vectors index yourself. You own the infra end to end.

Smoo-powered: point the gateway at https://llm.smoo.ai/v1 for unified billing + model routing, or skip the deploy entirely and let lom.smoo.ai run the smooth-operator service for you.

🧩 Part of Smoo AI {#part-of-smoo-ai}

@smooai/deploy is built and open-sourced by Smoo AI — the AI-powered business platform with AI built into every product: CRM, customer support, campaigns, field service, observability, and developer tools.

🤝 Contributing

Issues and PRs welcome. Keep deploys in CI — never deploy locally.

📄 License

MIT © Smoo AI.


Built by Smoo AI — AI built into every product.

About

Shared Smoo AI deploy primitives — reusable SST v4 constructs (API GW WebSocket + Rust Lambda + DynamoDB + S3 Vectors) and a Helm/ArgoCD chart. Consumed by smooth-operator and dogfooded by Smoo AI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages