Embed Codex in your Go application
If you already have a go application with real users, running Codex as a separate tool gets awkward pretty fast.
I wanted to run prompts from backend code, stream updates to my own UI, and keep approval behavior under my own control. To make that easier I put together github.com/pmenglund/codex-sdk-go, which talks to codex app-server over JSON-RPC.
The basic flow is simple:
- create a client
- start a thread
- run turns
- close the client when done
A minimal example:
package main
import (
"context"
"fmt"
"log/slog"
"os"
"github.com/pmenglund/codex-sdk-go"
)
func main() {
ctx := context.Background()
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelInfo}))
client, err := codex.New(ctx, codex.Options{Logger: logger})
if err != nil {
panic(err)
}
defer client.Close()
thread, err := client.StartThread(ctx, codex.ThreadStartOptions{})
if err != nil {
panic(err)
}
result, err := thread.Run(ctx, "Diagnose the test failure and propose a fix", nil)
if err != nil {
panic(err)
}
fmt.Println(result.FinalResponse)
}
I designed codex.New so the context is only used during initialization. Once the client has started, process lifetime is handled by Close.
For quick demos I usually do auto-approval:
client, err := codex.New(ctx, codex.Options{
Logger: logger,
ApprovalHandler: codex.AutoApproveHandler{Logger: logger},
})
For production I recommend writing your own approval handler and explicitly deciding what should be allowed automatically.
Another thing I like is structured output. Instead of parsing free-form text, you can give Codex a schema and get predictable data back:
schema := codex.MustJSON(map[string]any{
"type": "object",
"properties": map[string]any{
"summary": map[string]any{"type": "string"},
"status": map[string]any{"type": "string", "enum": []string{"ok", "action_required"}},
},
"required": []string{"summary", "status"},
"additionalProperties": false,
})
_, err := thread.RunInputs(
ctx,
[]codex.Input{codex.TextInput("Summarize repo status")},
&codex.TurnOptions{OutputSchema: schema},
)
If you’re building tooling like code review helpers, migration assistants, or incident support inside an existing go service, this has worked well for me.