Skip to content

Add bindings-backed Go SDK implementation#260

Merged
CoderOMaster merged 12 commits into
usemoss:mainfrom
anirudh-makuluri:go-sdk
Jun 16, 2026
Merged

Add bindings-backed Go SDK implementation#260
CoderOMaster merged 12 commits into
usemoss:mainfrom
anirudh-makuluri:go-sdk

Conversation

@anirudh-makuluri

@anirudh-makuluri anirudh-makuluri commented May 23, 2026

Copy link
Copy Markdown
Contributor

Pull Request Checklist

Please ensure that your PR meets the following requirements:

  • I have read the CONTRIBUTING guide.
  • I have updated the documentation (if applicable).
  • My code follows the style guidelines of this project.
  • I have performed a self-review of my own code.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.

Description

This PR adds the first bindings-backed Go SDK implementation for Moss.

What’s included:

  • adds sdks/go/bindings as a low-level CGO wrapper over libmoss
  • wires sdks/go/sdk to use the bindings layer for index management, document operations, local load/unload, and local query

Scope of this PR:

  • this is intended to land the core Go implementation first
  • current in-repo usage works and has been validated locally
  • external distribution / install ergonomics are intentionally left for follow-up work
  • for now, usage still requires an external libmoss C SDK plus -tags libmoss

Validation:

  • cd sdks/go/bindings && go test ./...
  • cd sdks/go/sdk && go test ./...
  • local end-to-end validation of:
    • create
    • get index / get docs
    • load
    • query
    • add docs
    • delete docs
    • delete index

Fixes #227

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Open in Devin Review

devin-ai-integration[bot]

This comment was marked as resolved.

@HarshaNalluru HarshaNalluru requested review from Copilot and removed request for yatharthk2 June 11, 2026 22:11
@HarshaNalluru

Copy link
Copy Markdown
Contributor

@CoderOMaster can you do a deep review?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a bindings-backed Go SDK for Moss by adding a low-level CGO wrapper over libmoss and wiring the public Go SDK to use that bindings layer for index management, document mutation, local load/unload, and local query.

Changes:

  • Added sdks/go/bindings module (CGO-backed, with -tags libmoss stub fallback).
  • Added sdks/go/sdk module implementing a typed Go client that uses the bindings for manage + local runtime operations.
  • Added examples, unit tests, and env-gated integration tests for the new Go SDK.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
sdks/go/README.md Top-level overview of the two-layer Go SDK/bindings structure and requirements.
sdks/go/sdk/go.mod Defines the Go SDK module and replaces the local bindings module.
sdks/go/sdk/README.md Documents installation, quick start, examples, and integration testing workflow.
sdks/go/sdk/moss/client.go Implements the public Client with lazy-initialized manage + index runtimes.
sdks/go/sdk/moss/options.go Compatibility options retained from earlier scaffolding.
sdks/go/sdk/moss/models.go Defines public SDK models/options/results.
sdks/go/sdk/moss/errors.go Defines public SDK error values and compatibility HTTPError.
sdks/go/sdk/moss/conversion.go Converts between bindings-layer types and public SDK types.
sdks/go/sdk/moss/read.go Adds bindings-backed index/document read operations.
sdks/go/sdk/moss/mutation.go Adds bindings-backed mutations plus job polling support.
sdks/go/sdk/moss/query.go Adds local query API and filter serialization support.
sdks/go/sdk/moss/local.go Adds local load/unload/refresh operations via bindings.
sdks/go/sdk/moss/client_test.go Unit tests for client behavior against fake runtimes.
sdks/go/sdk/moss/mutation_test.go Unit tests for mutation behaviors and polling logic.
sdks/go/sdk/moss/integration_test.go Env-gated end-to-end integration test using real bindings when available.
sdks/go/sdk/examples/basic/main.go Runnable example demonstrating create/load/query/delete.
sdks/go/sdk/examples/custom-embeddings/main.go Runnable example demonstrating caller-provided embeddings workflow.
sdks/go/bindings/go.mod Defines the bindings module.
sdks/go/bindings/README.md Documents the -tags libmoss workflow and required env flags.
sdks/go/bindings/errors.go Defines ErrBindingsUnavailable for non-libmoss builds.
sdks/go/bindings/models.go Defines bindings-layer data structures used by the CGO wrapper.
sdks/go/bindings/stub.go Provides the non-libmoss stub implementation returning ErrBindingsUnavailable.
sdks/go/bindings/libmoss.go Implements the CGO wrapper around libmoss manage + local runtime APIs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread sdks/go/sdk/moss/conversion.go Outdated
Comment on lines +66 to +72
timeTaken := value.TimeTakenMs
return SearchResult{
Docs: docs,
Query: value.Query,
IndexName: value.IndexName,
TimeTakenMs: &timeTaken,
}
Comment on lines +290 to +292
func (m *IndexManager) LoadQueryModel(indexName string) error {
return nil
}
Comment on lines +50 to +55
func (c *ManageClient) CreateIndex(name string, docs []DocumentInfo, modelID string) (MutationResult, error) {
input, err := newCDocumentInput(docs)
if err != nil {
return MutationResult{}, err
}
defer input.free()
Comment on lines +327 to +332
func (m *IndexManager) query(indexName, query string, queryEmbedding []float32, topK int, alpha float32, filterJSON *string) (SearchResult, error) {
cName := C.CString(indexName)
defer C.free(unsafe.Pointer(cName))
cQuery := C.CString(query)
defer C.free(unsafe.Pointer(cQuery))

Comment thread sdks/go/sdk/README.md Outdated
Comment on lines +26 to +30
From this repository, use the module at:

```go
github.com/usemoss/moss/sdks/go/sdk/moss
```

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

Open in Devin Review

Comment on lines +290 to +292
func (m *IndexManager) LoadQueryModel(indexName string) error {
return nil
}

@devin-ai-integration devin-ai-integration Bot Jun 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 LoadQueryModel is a no-op in the bindings layer

LoadQueryModel at sdks/go/bindings/libmoss.go:290-292 always returns nil. The SDK calls it after loading non-custom indexes (sdks/go/sdk/moss/local.go:39-42). This means for standard model indexes (e.g., moss-minilm), no explicit query model loading occurs. This is presumably because the C SDK's moss_client_load_index handles model loading internally, but it's worth confirming — if the C API does require a separate model-load step, text queries on non-custom indexes would silently fail or produce incorrect results.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread sdks/go/bindings/libmoss.go
Comment thread sdks/go/sdk/moss/query.go Outdated
if err != nil {
return SearchResult{}, err
}
if !manager.HasIndex(indexName) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add cloud query fallback for unloaded indexes

Go returns ErrIndexNotLoaded when Query is called before LoadIndex, at query.go (line 23). Python and JS both fall back to cloud query instead.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

Open in Devin Review

Comment on lines +465 to +477
func (m *IndexManager) withClient(call func(*C.MossClient) C.MossResult) error {
if m == nil {
return ErrClientClosed
}
m.mu.RLock()
defer m.mu.RUnlock()
if m.ptr == nil {
return ErrClientClosed
}
return withErrorThread(func() C.MossResult {
return call(m.ptr)
})
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 IndexManager.withClient uses RLock — concurrent RefreshIndex + Query depends on libmoss thread safety

IndexManager.withClient at sdks/go/bindings/libmoss.go:465 uses m.mu.RLock(), allowing RefreshIndex (line 338) and query (line 373) to run concurrently since both call withClient. This is correct from the Go SDK's perspective — the RWMutex protects m.ptr from being freed during use — but it means the C library must handle concurrent moss_client_refresh_index + moss_client_query calls on the same MossClient pointer safely. This matches the pattern where LoadIndex/UnloadIndex take exclusive Lock() (they mutate m.loaded), while read-path operations share RLock(). Worth confirming that libmoss supports this concurrency model.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@anirudh-makuluri

Copy link
Copy Markdown
Contributor Author

Just a heads up: this is not the final user-ready distribution story yet.

Right now the Go SDK works, but native/local runtime usage requires the libmoss C SDK to be installed locally so libmoss.h and libmoss.so are available. For example, we currently validate the examples with:

go run -tags libmoss ./examples/basic

To make this fully user-ready, we still need to decide on the distribution path: cloud-first default with optional native acceleration, bundled native libs, a setup helper, separate cloud/native packages, etc.

Happy to discuss the best direction whenever you guys are free.

devin-ai-integration[bot]

This comment was marked as resolved.

@CoderOMaster

Copy link
Copy Markdown
Collaborator

@anirudh-makuluri i think using libmoss is fine for now, rest you can update and address all the review comments

@anirudh-makuluri

anirudh-makuluri commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

@CoderOMaster yes, agreed. We'll keep using libmoss for the Go SDK.

My earlier message was more about how libmoss should get onto the user's machine. Right now I'm testing by installing it locally, setting CGO_CFLAGS / CGO_LDFLAGS, and running with -tags libmoss. That works for development, but I don't think we want end users to do all of that manually.

A few possible options:

  1. Publish prebuilt libmoss artifacts per platform/arch, e.g. Linux, macOS, Windows with amd64/arm64 variants, and bundle or expose them through the Go bindings module so the bindings link the right one automatically.
  2. Keep the current external libmoss requirement but add a setup helper/script that downloads the right C SDK release and configures CGO_CFLAGS, CGO_LDFLAGS, etc.
  3. Split the SDK into cloud-first and native packages, where the default Go SDK works without CGO for cloud operations, and native/local search is an optional package or build tag.
  4. Keep -tags libmoss as the advanced/native-runtime path for now, but document it clearly rather than treating it as the final install story.

I'd lean toward option 1. With the current structure, sdks/go/sdk can remain the public SDK and sdks/go/bindings can remain the native layer. If the bindings module includes the right prebuilt libmoss artifacts, users should only need:

go get github.com/usemoss/moss/sdks/go/sdk

devin-ai-integration[bot]

This comment was marked as resolved.

@CoderOMaster CoderOMaster requested a review from Copilot June 15, 2026 16:18
@CoderOMaster

Copy link
Copy Markdown
Collaborator

@anirudh-makuluri okay lets go with option 1. also can you also address copliot comments?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 4 comments.

Comment thread sdks/go/sdk/query.go
Comment on lines +19 to +24
if err := ctx.Err(); err != nil {
return SearchResult{}, err
}
if err := c.validateQueryRequest(indexName); err != nil {
return SearchResult{}, err
}
Comment thread sdks/go/sdk/query.go
Comment on lines +89 to +92
func (c *Client) queryCloud(ctx context.Context, indexName, query string, options *QueryOptions) (SearchResult, error) {
topK := defaultTopK
var embedding []float32
if options != nil {
Comment thread sdks/go/sdk/query.go
Comment on lines +55 to +62
if options.Filter != nil {
bytes, err := json.Marshal(options.Filter)
if err != nil {
return SearchResult{}, err
}
value := string(bytes)
filterJSON = &value
}
Comment thread sdks/go/sdk/local.go
Comment on lines +68 to +73
if err := ctx.Err(); err != nil {
return RefreshResult{}, err
}
if strings.TrimSpace(indexName) == "" {
return RefreshResult{}, ErrEmptyIndexName
}
devin-ai-integration[bot]

This comment was marked as resolved.

@anirudh-makuluri

Copy link
Copy Markdown
Contributor Author

Sounds good, thanks. The review comments should be addressed now.

For option 1, I think it’s better to handle the prebuilt libmoss artifacts in a follow-up branch/PR rather than expanding this one further. This PR can stay focused on landing the Go SDK and bindings-backed implementation, and the follow-up can add the platform-specific native artifacts under the bindings module plus the CGO selection/linking changes.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

Open in Devin Review

Comment thread sdks/go/sdk/query.go
@CoderOMaster CoderOMaster merged commit 3c06365 into usemoss:main Jun 16, 2026
12 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Go Bindings for Moss

4 participants