Thank you for your interest in contributing to aixgo! We welcome contributions from the community and are excited to work with you.
For comprehensive documentation, visit https://aixgo.dev
- Code of Conduct
- Ways to Contribute
- Development Setup
- Pull Request Process
- Code Style Guidelines
- Testing Requirements
- Documentation Standards
- Commit Message Format
- Copyright and Licensing
This project follows a standard code of conduct. Be respectful, inclusive, and professional in all interactions.
Found a bug? Please create an issue with:
- Clear description of the problem
- Steps to reproduce
- Expected vs actual behavior
- Environment details (OS, Go version, aixgo version)
- Minimal code sample if applicable
Have an idea? Open a discussion or issue with:
- Use case description
- Proposed solution
- Alternative approaches considered
- Why this benefits the broader community
We welcome pull requests for:
- Bug fixes
- New agent types
- LLM provider integrations
- Performance optimizations
- Documentation improvements
- Test coverage improvements
Documentation contributions are highly valued:
- Tutorial content
- Example applications
- API documentation improvements
- Architecture explanations
- Migration guides
Built something with aixgo? Share it!
- Post in GitHub Discussions "Show & Tell"
- Submit example to the
examples/directory - Write a blog post (we'll link to it)
- Go 1.26 or later
- Git
- Make (optional, for convenience commands)
# Clone the repository
git clone https://github.com/aixgo-dev/aixgo.git
cd aixgo
# Install dependencies
go mod download
# Build the project
go build ./...
# Run tests to verify setup
go test ./...aixgo/
├── agents/ # Agent implementations
├── config/ # Example configurations
├── docs/ # Documentation
├── examples/ # Example applications
├── internal/
│ ├── agent/ # Core agent types and factory
│ ├── llm/ # LLM integration and validation
│ ├── observability/# OpenTelemetry integration
│ └── supervisor/ # Supervisor implementation
├── proto/ # Message protocol
├── aixgo.go # Main entry point
└── runtime.go # Communication runtime
# Fork the repository on GitHub, then:
git clone https://github.com/YOUR_USERNAME/aixgo.git
cd aixgo
git remote add upstream https://github.com/aixgo-dev/aixgo.gitgit checkout -b feature/your-feature-name
# or
git checkout -b fix/your-bug-fix- Write clean, idiomatic Go code
- Follow existing code patterns and conventions
- Add tests for new functionality
- Update documentation as needed
- Keep commits focused and atomic
# Run all tests
go test ./...
# Run with race detector
go test -race ./...
# Check test coverage
go test -cover ./...
# Run linters
go vet ./...
golangci-lint run- Add godoc comments for exported functions and types
- Update README.md if adding features
- Add examples if introducing new patterns
- Update relevant documentation
- Push your branch to your fork
- Open a PR against
mainbranch - Fill out the PR template completely
- Link any related issues
- Wait for review and address feedback
Before submitting, ensure:
- Tests pass locally (
go test ./...) - No race conditions (
go test -race ./...) - Code is formatted (
gofmt -s -w .) - Linters pass (
go vet ./...) - Documentation updated
- Commit messages follow conventions
- PR description explains what and why
- Follow Effective Go
- Use
gofmt -sfor formatting - Run
go vetbefore committing - Keep functions focused and small
- Prefer clarity over cleverness
// Package names: lowercase, single word
package agent
// Exported types: PascalCase
type Agent struct {}
// Unexported types: camelCase
type agentImpl struct {}
// Interfaces: noun or adjective
type Runtime interface {}
type Validator interface {}
// Methods: PascalCase for exported, camelCase for unexported
func (a *Agent) Start(ctx context.Context) error {}
func (a *Agent) think(input string) (string, error) {}// Always check errors explicitly
result, err := operation()
if err != nil {
return fmt.Errorf("operation failed: %w", err)
}
// Use %w for error wrapping
return fmt.Errorf("failed to process: %w", err)
// Provide context in error messages
if err != nil {
return fmt.Errorf("agent %s failed to start: %w", a.name, err)
}// Exported functions must have godoc comments
// explaining what they do, not how they do it.
//
// Example:
//
// agent := NewAgent(WithName("analyzer"))
// err := agent.Start(ctx)
func NewAgent(opts ...Option) *Agent {
// ...
}
// Unexported functions should have comments explaining
// non-obvious logic or design decisions
func (a *Agent) think(input string) (string, error) {
// Use exponential backoff for retries to avoid
// overwhelming the LLM API during outages
}- Aim for >80% coverage for new code
- 100% coverage for critical paths (validation, factory, runtime)
- Use table-driven tests for multiple scenarios
func TestAgentStart(t *testing.T) {
t.Parallel() // Enable parallel execution when safe
tests := []struct {
name string
input input
want output
wantErr bool
}{
{
name: "successful start",
input: validInput,
want: expectedOutput,
wantErr: false,
},
// More test cases...
}
for _, tt := range tests {
tt := tt // Capture range variable
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
// Test implementation
got, err := operation(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("wanted error: %v, got: %v", tt.wantErr, err)
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("wanted: %v, got: %v", tt.want, got)
}
})
}
}Use the provided test utilities:
// MockRuntime for testing agents
mockRT := agent.NewMockRuntime()
ctx := agent.ContextWithRuntime(context.Background(), mockRT)
// MockOpenAIClient for testing ReAct agents
mockClient := agents.NewMockOpenAIClient()
mockClient.AddResponse(expectedResponse, nil)
// MockFileReader for testing config loading
mockReader := aixgo.NewMockFileReader()
mockReader.AddFile("config.yaml", configData)Always test with race detector:
go test -race ./...All exported symbols must have godoc comments:
// Agent represents an autonomous AI agent that processes messages
// and executes tasks within an aixgo system. Agents operate under
// supervisor coordination and communicate via the runtime layer.
//
// Agents support three built-in roles:
// - Producer: Generates periodic messages
// - ReAct: Reasoning and acting with LLM integration
// - Logger: Consumes and logs messages
//
// Example usage:
//
// agent := NewAgent(
// WithName("analyzer"),
// WithRole("react"),
// )
// if err := agent.Start(ctx); err != nil {
// log.Fatal(err)
// }
type Agent struct {
// ...
}- Follow markdownlint rules
- Specify language for all code blocks
- Include blank lines after headings
- Keep line length reasonable (<120 chars)
- Use relative links for internal docs
All examples must:
- Be copy-pasteable and runnable
- Include necessary imports
- Show expected output
- Handle errors explicitly
- Include explanatory comments
We use Conventional Commits format:
<type>(<scope>): <description>
[optional body]
[optional footer]
feat: New featurefix: Bug fixdocs: Documentation changestest: Adding or updating testsrefactor: Code changes that neither fix bugs nor add featuresperf: Performance improvementschore: Maintenance tasks, dependency updates
feat(agents): add classifier agent type
Add a new classifier agent that categorizes incoming messages
based on configurable rules or LLM-based classification.
Closes #42
fix(runtime): prevent deadlock in channel send
Fixed race condition in Runtime.Send() that could cause
deadlock under high concurrency. Added mutex protection around
channel map access.
Fixes #38
docs(readme): add installation instructions
Added detailed installation section with examples for different
package managers and build-from-source instructions.
- All contributions are licensed under the MIT License
- By submitting a PR, you agree to license your contribution under MIT
- You retain copyright to your contributions
- No Contributor License Agreement (CLA) required
No copyright headers required in source files. The repository LICENSE file covers all contributions.
- Questions: Use GitHub Discussions
- Bugs: Create an Issue
- Feature Ideas: Start a Discussion first, then create an Issue if consensus
Contributors will be recognized:
- In release notes for significant contributions
- In the project README (planned contributors section)
- Via GitHub's built-in contributor tracking
Thank you for contributing to aixgo!