Skip to main content

Quickstart: Hello Solution

By the end of this tutorial you will have a FastAPI service running in a local Kubernetes cluster, packaged as a Helm chart that wraps the platform’s em-service base chart, and reachable by curl. Total time: 30 minutes or less. If it takes longer, that’s a guide bug — please report via the 👎 thumbs at the bottom of this page.
This tutorial keeps every command and config snippet inline. Its one external dependency is the platform’s em-service base chart, pulled from Emergence’s private container registry during install — registry access is granted to the Emergence team and Solution/Agent design partners (you authenticate with helm registry login in the install step).

Prerequisites

Install these tools. Versions are floors, not pins — newer is fine.
ToolVersionPurpose
Docker24+Container runtime for Kind
Kind0.20+Local Kubernetes cluster
kubectl1.28+Kubernetes CLI
Helm3.13+Package manager for Kubernetes
uv0.4+Python project manager
brew install docker kind kubectl helm uv

What you’ll build

A solution called hello-solution with one component (api) that exposes:
  • GET /healthz{"status":"ok"} for k8s probes
  • GET /echo?msg=... → echoes the message back
The image is built locally and loaded into Kind (no registry needed). The Helm chart wraps em-service v0.0.15 with alias: api, so you’ll see how multi-component solutions extend (just add another alias).

Steps

1

Create the project layout

Pick a working directory and scaffold these files:
hello-solution/
├── packages/api/
│   ├── pyproject.toml
│   └── src/api/
│       └── main.py
├── Dockerfile
└── charts/hello-solution/
    ├── Chart.yaml
    └── values.yaml
mkdir -p hello-solution/packages/api/src/api hello-solution/charts/hello-solution
cd hello-solution
2

Write the FastAPI app

from fastapi import FastAPI

app = FastAPI(title="hello-solution")

@app.get("/healthz")
async def healthz() -> dict[str, str]:
    return {"status": "ok"}

@app.get("/echo")
async def echo(msg: str = "hi") -> dict[str, str]:
    return {"echo": msg}
3

Write the Dockerfile

A multi-stage build keeps the runtime image small.
Dockerfile
FROM python:3.12-slim AS build
WORKDIR /app
RUN pip install --no-cache-dir uv
COPY packages/api/pyproject.toml packages/api/pyproject.toml
COPY packages/api/src packages/api/src
RUN uv pip install --system --no-cache-dir ./packages/api

FROM python:3.12-slim
COPY --from=build /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY --from=build /usr/local/bin/uvicorn /usr/local/bin/uvicorn
EXPOSE 8000
CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000"]
4

Write the Helm chart

The chart declares one em-service subchart, aliased as api. The platform’s em-service (v0.0.15) handles Deployment, Service, probes, env vars — you only configure your image and ports. To add a worker later, you’d add another em-service entry with alias: worker and configure it under that alias key in values.yaml. See em-service Chart for the full values reference.
apiVersion: v2
name: hello-solution
description: A minimal CRAFT solution
type: application
version: 0.1.0
appVersion: "0.1.0"
dependencies:
  - name: em-service
    alias: api
    version: 0.0.15        # latest tag published to the OCI registry
    repository: oci://ghcr.io/emergenceai/em-charts
5

Create a Kind cluster and load your image

# Create cluster
kind create cluster --name hello-solution

# Build and load image
docker build -t hello-solution-api:dev .
kind load docker-image hello-solution-api:dev --name hello-solution
kind load docker-image makes your local image available inside the cluster without a registry.
6

Install the chart

# Authenticate to the private em-charts registry first (team / design-partner access)
helm registry login ghcr.io
helm dependency update ./charts/hello-solution
helm upgrade --install hello-solution ./charts/hello-solution \
  --namespace em-hello-solution --create-namespace \
  --wait --timeout 5m
First install pulls em-service from ghcr.io/emergenceai/em-charts, a private registry — helm registry login ghcr.io authenticates you (access is granted to the Emergence team and Solution/Agent design partners).
7

Smoke-test it

kubectl port-forward -n em-hello-solution svc/hello-solution-api 8000:8000 &

curl -s "http://localhost:8000/healthz" | jq .
# {"status":"ok"}

curl -s "http://localhost:8000/echo?msg=ship%20it" | jq .
# {"echo":"ship it"}
If both calls succeed, you have shipped your first CRAFT solution.
8

Tear down

kill %1 2>/dev/null  # stop port-forward
helm uninstall hello-solution -n em-hello-solution
kubectl delete namespace em-hello-solution
kind delete cluster --name hello-solution

What you just did

You wrapped a 25-line FastAPI app in a Helm chart that depends on the platform’s em-service base chart, deployed it to a namespace named em-<solution> (the platform convention), and reached it via port-forward. You did not configure auth, secrets, storage, or LLMs yet — those are the next how-tos:

Register a solution

Make this naming + namespace pattern systematic.

Authenticate users

Protect /echo with JWT validation.

Manage secrets

Wire a secret-backed env var into your chart.

Local development

Loop faster with docker-compose + hot reload.