Go AI orchestrator using Cloudflare LLMs with stateful semantic memory.
315
This service acts as an AI Orchestrator that integrates with Cloudflare's AI Gateway/Workers API. It implements stateful, persistent chat sessions with a high-performance in-memory memory repository, semantic context retrieval via cosine similarity, and OpenTelemetry instrumentation.
The following hierarchical structure illustrates the HTTP request routing, Dependency Injection layout, Port/Adapter boundary, and external integration points of the AI Orchestrator:
└── HTTP Client (Frontend / API consumer)
└── [POST /api/v1/chat or /chat/persistent]
└── HTTP Router (src/api/rest/v1/router.go)
└── Route Matching & Middleware Injection
└── AI Handlers (src/api/rest/v1/handlers/ai_handlers.go)
├── Dependency Injection Container (src/shared/di/providers.go)
│ └── Resolves and injects the Orchestrator Service
│
└── AI Orchestrator Service (src/features/ai_orchestrator/service.go)
├── Port: CloudflareClient (src/features/ai_orchestrator/ports.go)
│ └── Adapter: CloudflareAdapter (src/infra/adapters/cloudflare_adapter.go)
│ └── REST Calls -> External Cloudflare AI Gateway/Workers API
│
└── Port: MemoryRepository (src/features/ai_orchestrator/ports.go)
└── Adapter: MemoryRepository (src/infra/adapters/memory_repo.go)
└── Thread-safe In-Memory Vector DB (Cosine Similarity retrieval)
This hierarchical decision tree outlines the conditional execution paths for stateless vs. stateful chat requests:
└── Incoming Chat Request
├── Route: /api/v1/chat (Stateless Flow)
│ ├── [Step 1] Parse payload (messages list)
│ ├── [Step 2] Send messages directly to Cloudflare LLM
│ └── [Step 3] Return AI assistant response to the client
│
└── Route: /api/v1/chat/persistent (Stateful Flow)
├── [Step 1] Parse payload (user_id, message text)
├── [Step 2] Generate embedding vector for user message via Cloudflare AI
├── [Step 3] Fetch user memory history from In-Memory Memory Repository
├── [Decision] Does user have past conversational memory?
│ ├── YES (Retrieve Context)
│ │ ├── [Sub-Step] Compute Cosine Similarity between user message vector and all past vectors
│ │ ├── [Sub-Step] Filter and sort memories where similarity >= threshold (default: 0.7)
│ │ ├── [Sub-Step] Select top K context-rich memories (default: 5)
│ │ └── [Sub-Step] Prepend retrieved context to the prompt as system instructions
│ └── NO (Skip Context Retrieval)
│ └── [Sub-Step] Proceed with empty conversational history context
│
├── [Step 4] Send complete prompt (context + current message) to Cloudflare LLM
├── [Step 5] Receive LLM AI response text
├── [Step 6] Generate embedding vector for assistant response text via Cloudflare AI
├── [Step 7] Atomically store both User and Assistant turns in the Memory Repository
└── [Step 8] Return AI response + semantic context metadata to the client
.
├── Dockerfile
├── docker-compose.yaml
├── go.mod
├── go.sum
├── test_api.sh
├── test_cloudflare_real.sh
├── contracts/
│ ├── changelog.md
│ └── openapi/
│ └── v1.yaml
├── scripts/
│ └── deploy_docker.sh
└── src/
├── main.go
├── api/
│ └── rest/
│ └── v1/
│ ├── router.go
│ └── handlers/
│ └── ai_handlers.go
├── features/
│ └── ai_orchestrator/
│ ├── index.go
│ ├── ports.go
│ ├── service.go
│ └── types.go
├── infra/
│ └── adapters/
│ ├── cloudflare_adapter.go
│ └── memory_repo.go
└── shared/
├── di/
│ └── providers.go
└── tracing/
└── otel.go
Key components: Multi-stage Dockerfile, OpenAPI contracts, automated deploy_docker.sh release script, Hexagonal Domain layer ai_orchestrator, and Cloudflare API + In-Memory Vector adapters.
The service is configured using the following environment variables:
| Variable | Description | Default Value |
|---|---|---|
PORT | The port the HTTP server binds to | 8080 |
CF_ACCOUNT_ID | Cloudflare Account ID | local-account (Triggers mock mode if default) |
CF_API_TOKEN | Cloudflare AI Workers Token (cfut_...) | local-token (Triggers mock mode if default) |
CF_ACCESS_JWT_ASSERTION | Cloudflare Access API Token (cfat_...) | Optional / None |
CF_EMBEDDING_MODEL | The default text embedding model ID | @cf/baai/bge-small-en-v1.5 |
AI_DEFAULT_MODEL | The default chat/LLM model ID | @cf/meta/llama-3.1-8b-instruct |
Ensure you have Go 1.21+ installed.
export PORT=8080
export CF_ACCOUNT_ID="your-cloudflare-account-id"
export CF_API_TOKEN="your-cloudflare-api-token"
export CF_ACCESS_JWT_ASSERTION="your-cloudflare-access-jwt-assertion"
go run src/main.go
To build a highly optimized, multi-stage production Docker image:
docker build -t chiefj/ai-service:latest .
A deployment script is provided at scripts/deploy_docker.sh that automates building, tagging, logging in, and pushing the image as the first stable release (v1.0.0), stable, and latest:
./scripts/deploy_docker.sh
To run the built Docker container locally mapping port 8080:
docker run -d \
--name ai-service-test \
-p 8080:8080 \
-e CF_ACCOUNT_ID="your-cloudflare-account-id" \
-e CF_API_TOKEN="your-cloudflare-api-token" \
-e CF_ACCESS_JWT_ASSERTION="your-cloudflare-access-jwt-assertion" \
chiefj/ai-service:latest
The in-memory session memory repository stores active chat session records under a high-performance concurrent map (sync.RWMutex). Each record holds the conversational text history alongside the 384-dimensional float32 embedding vector (@cf/baai/bge-small-en-v1.5).
15 minutes (15 * time.Minute TTL).Based on server RAM allocations:
| Allocated RAM | Approx. Active Sessions | Approx. Total Messages Stored |
|---|---|---|
100 MB | ~10,000 | ~25,000 |
500 MB | ~50,000 | ~125,000 |
1 GB | ~100,000 | ~250,000 |
4 GB | ~400,000 | ~1,000,000 |
| Operation | Latency | Complexity | Detail |
|---|---|---|---|
| In-Memory Session Lookup | < 1 µs | O(1) | Read-locked hash map retrieval |
| Cosine Similarity Search | < 1 ms | O(N) | Blazing-fast float32 array calculations |
| Embedding Generation | 50 - 150 ms | Network-Bound | REST Call to Cloudflare Workers AI |
| LLM Chat Inference | 300 - 800 ms | Network-Bound | REST Call to Cloudflare Workers AI Llama-3 |
The service has deep native tracing capabilities built with OpenTelemetry (go.opentelemetry.io/otel). The InitTracer provider formats and exports service traces to standard out or compatible collectors.
http.method, http.route, api.version (v1)feature.name (set to ai_orchestrator)ai.model and ai.embedding_modeluser.idspan.RecordError(err) and marked with codes.Error status code for automatic alerting inside modern observability dashboards.Retrieves the catalog of AI models from Cloudflare.
curl -s -f http://localhost:8080/api/v1/models
[
{
"id": "31097538-a3ff-4e6e-bb56-ad0e1f428b61",
"name": "@cf/meta/llama-3-8b-instruct-awq",
"description": "Quantized (int4) generative text model with 8 billion parameters from Meta.",
"provider": ""
},
{
"id": "053d5ac0-861b-4d3b-8501-e58d00417ef8",
"name": "@cf/google/gemma-3-12b-it",
"description": "Gemma 3 models are well-suited for a variety of text generation and image understanding tasks...",
"provider": ""
},
{
"id": "01bc2fb0-4bca-4598-b985-d2584a3f46c0",
"name": "@cf/baai/bge-large-en-v1.5",
"description": "BAAI general embedding (Large) model that transforms any given text into a 1024-dimensional vector",
"provider": ""
}
]
Executes a stateless chat completion against a designated LLM model.
curl -s -f -X POST http://localhost:8080/api/v1/chat \
-H "Content-Type: application/json" \
-d '{
"model": "@cf/meta/llama-3-8b-instruct",
"messages": [
{"role": "user", "content": "Explain Hexagonal Architecture in Go in one sentence."}
]
}'
{
"response": "In Go, Hexagonal Architecture, also known as Ports and Adapters Architecture, is a design pattern where the application's business logic is encapsulated in a \"domain layer\" and interacts with external dependencies through \"ports\" and \"adapters\", allowing for loose coupling and testability."
}
Initiates a session, generates a text embedding of the input, saves it in concurrent-safe memory, and processes the response.
curl -s -f -X POST http://localhost:8080/api/v1/chat/persistent \
-H "Content-Type: application/json" \
-d '{
"user_id": "live_user_123",
"message": "Hello Cloudflare! My favorite programming language is Go.",
"model": "@cf/meta/llama-3-8b-instruct",
"embedding_model": "@cf/baai/bge-small-en-v1.5"
}'
{
"response": "Hello there! I'm thrilled to hear that your favorite programming language is Go! As a cloud-based service, Cloudflare is heavily invested in the Go programming language. In fact, our entire web server is written in Go, and it's been a fantastic choice for us.\n\nWe've found that Go's concurrency features, performance, and simplicity make it an ideal language for building scalable and reliable systems. Our Go-based server has allowed us to handle massive traffic spikes and provide fast and secure connections to our customers.\n\nWhat do you love most about Go? Is it the concurrency model, the simplicity of the language, or something else entirely?",
"history": [
{
"role": "user",
"content": "Hello Cloudflare! My favorite programming language is Go."
},
{
"role": "assistant",
"content": "Hello there! I'm thrilled to hear that your favorite programming language is Go! As a cloud-based service, Cloudflare is heavily invested in the Go programming language..."
}
]
}
Queries the chat session. The orchestrator embeds the query, searches the memory repository via cosine similarity, retrieves the relevant context, appends history, and passes it to the LLM.
curl -s -f -X POST http://localhost:8080/api/v1/chat/persistent \
-H "Content-Type: application/json" \
-d '{
"user_id": "live_user_123",
"message": "What is my favorite programming language?",
"model": "@cf/meta/llama-3-8b-instruct",
"embedding_model": "@cf/baai/bge-small-en-v1.5"
}'
{
"response": "You told me earlier that your favorite programming language is Go!",
"history": [
{
"role": "user",
"content": "Hello Cloudflare! My favorite programming language is Go."
},
{
"role": "assistant",
"content": "Hello there!..."
},
{
"role": "user",
"content": "What is my favorite programming language?"
},
{
"role": "assistant",
"content": "You told me earlier that your favorite programming language is Go!"
}
]
}
Content type
Image
Digest
sha256:1a994ad4b…
Size
5.7 MB
Last updated
4 months ago
docker pull chiefj/ai-service