\n\n\n\n My Journey: Contributing to Open Source AI as a Non-Maintainer - ClawDev My Journey: Contributing to Open Source AI as a Non-Maintainer - ClawDev \n

My Journey: Contributing to Open Source AI as a Non-Maintainer

📖 10 min read•1,810 words•Updated May 15, 2026

Hey everyone, Kai Nakamura here from clawdev.net, your friendly neighborhood AI dev enthusiast. Today, I want to talk about something that’s been on my mind a lot lately, especially as I look at the projects I’m involved in and the broader AI community: contributing to open source, specifically when you’re not a core maintainer. We all know the big names, the legendary committers, the people who started the projects we use every day. But what about the rest of us? The ones who use the libraries, find the bugs, wish for a new feature, or simply want to improve the documentation? That’s where the real magic happens, and frankly, it’s where a lot of AI innovation gets its practical edge.

Beyond the First Pull Request: Sustained, Practical Contributions

A few years ago, when I first dipped my toes into open source, I thought it was all about submitting a massive feature or fixing a critical bug. My first contribution was a typo fix in a README for a relatively obscure Python library. I remember the rush when it got merged – almost as good as getting my first job offer! But I quickly fell into a trap that I see many new contributors face: after that initial rush, I didn’t know what to do next. I waited for another obvious bug to appear, or for a feature idea to strike me like lightning. This meant my contributions were sporadic, driven by chance rather than intention.

What I’ve learned since then, particularly in the fast-moving AI space, is that sustained, practical contributions – even small ones – are far more valuable than sporadic, grand gestures. It’s not about being a hero once; it’s about being a reliable helper consistently. For AI projects, where models evolve, data pipelines shift, and documentation needs constant updating, this kind of steady support is crucial.

The “Silent Gardener” Approach

I like to think of this as the “silent gardener” approach. You’re not planting the whole forest, but you’re consistently watering the saplings, pulling out weeds, and ensuring the existing plants thrive. This is especially true for AI projects because they often involve complex interdependencies: a change in a model architecture might necessitate updates to preprocessing scripts, inference code, and, most importantly, the examples demonstrating its use.

Let me give you a concrete example. Last year, I was working with a popular library for federated learning. It was brilliant, but some of the example notebooks were using deprecated `tf.compat.v1` functions, even though the library itself had moved to TensorFlow 2.0. The core team was busy pushing new features, and this detail, while minor, was making it harder for newcomers (like me at the time!) to get started without hitting errors.

Instead of just complaining in an issue, I took it upon myself to update one of the notebooks. It wasn’t a groundbreaking change, but it involved carefully rewriting the TensorFlow parts to use the modern API. It took me maybe an hour or two, mostly because I had to set up the environment and test it properly. When I submitted the PR, it was merged within a day, and I got a nice message from one of the maintainers thanking me for making their examples more accessible. That feeling was even better than my first typo fix because I knew I had directly eased someone else’s onboarding pain.

Here’s a simplified snippet of what that change looked like, moving from an older TF 1.x style to TF 2.x for a simple Keras model:


# Old (TF 1.x style, often seen with tf.compat.v1)
import tensorflow as tf
from tensorflow.python.keras.layers import Dense, Flatten
from tensorflow.python.keras.models import Sequential

def create_model_old():
 model = Sequential([
 Flatten(input_shape=(28, 28)),
 Dense(128, activation='relu'),
 Dense(10, activation='softmax')
 ])
 model.compile(optimizer='adam',
 loss='sparse_categorical_crossentropy',
 metrics=['accuracy'])
 return model

# New (TF 2.x style)
import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.models import Sequential

def create_model_new():
 model = Sequential([
 Flatten(input_shape=(28, 28)),
 Dense(128, activation='relu'),
 Dense(10, activation='softmax')
 ])
 model.compile(optimizer='adam',
 loss='sparse_categorical_crossentropy',
 metrics=['accuracy'])
 return model

The difference might seem small here, but imagine this across dozens of functions and files. Cleaning that up significantly improved the user experience.

Where to Find Your Gardening Plot: Practical Contribution Areas

So, how do you find these “gardening plots” where your contributions can truly shine without requiring you to be a deep expert in the project’s core algorithms? Here are a few areas I’ve found incredibly rewarding:

1. Documentation, Examples, and Tutorials

  • Updating out-of-date information: This is low-hanging fruit. If you just used a library and found a discrepancy between the docs and the actual behavior, open a PR! It helps everyone.
  • Adding practical examples: Core examples are often minimal. Can you add an example showing how to integrate the library with another popular tool (e.g., how to use a custom PyTorch dataset with a specific data augmentation library)?
  • Improving clarity: Sometimes, a paragraph is technically correct but hard to understand for a newcomer. Rewriting it for better clarity is a huge win.
  • Translating docs: If you’re multilingual, translating documentation is an invaluable contribution to global accessibility.

2. Bug Reports and Reproducible Examples

This might sound basic, but a well-written bug report with a minimal, reproducible example is a contribution in itself. Maintainers spend countless hours trying to understand vague bug descriptions. Providing a clear path to reproduce the issue saves them immense time and effort, making it much more likely your bug will be fixed quickly.


# Example of a good bug report snippet (imagine this in a GitHub Issue)
## Issue: Model fails to load with custom layer when saved in HDF5 format

**Library Version:** `my_ai_library==0.7.1`, `tensorflow==2.12.0`
**OS:** macOS Sonoma 14.4
**Python Version:** 3.10.12

**Description:**
When attempting to load a Keras model saved in HDF5 format, if that model contains a custom layer defined within the same script, `tf.keras.models.load_model` raises a `ValueError` indicating it cannot find the custom layer class, even when `custom_objects` is provided. This only occurs with HDF5; SavedModel format works correctly.

**Steps to Reproduce:**
1. Create a custom Keras layer.
2. Build a simple model incorporating this layer.
3. Save the model in HDF5 format.
4. Attempt to load the model using `load_model` with `custom_objects` pointing to the custom layer class.

**Minimal Reproducible Code:**
```python
import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Layer, Dense

# 1. Custom Layer Definition
class CustomActivation(Layer):
 def __init__(self, **kwargs):
 super().__init__(**kwargs)

 def call(self, inputs):
 return tf.math.sin(inputs) # Simple custom activation

 def get_config(self):
 config = super().get_config()
 return config

# 2. Build Model
input_tensor = Input(shape=(10,))
x = Dense(5, activation='relu')(input_tensor)
output_tensor = CustomActivation()(x)
model = Model(inputs=input_tensor, outputs=output_tensor)
model.compile(optimizer='adam', loss='mse')

# 3. Save Model (HDF5)
model_path_hdf5 = "custom_model.h5"
model.save(model_path_hdf5) 
print(f"Model saved to {model_path_hdf5}")

# 4. Attempt to Load Model
try:
 loaded_model = tf.keras.models.load_model(
 model_path_hdf5,
 custom_objects={'CustomActivation': CustomActivation}
 )
 print("Model loaded successfully!")
 # Test inference
 dummy_input = tf.random.normal((1, 10))
 _ = loaded_model(dummy_input)
except ValueError as e:
 print(f"Error loading model: {e}")

# (Optional) Demonstrate working with SavedModel format
model_path_savedmodel = "custom_model_savedmodel"
model.save(model_path_savedmodel)
print(f"\nModel saved to {model_path_savedmodel}")
loaded_model_sm = tf.keras.models.load_model(model_path_savedmodel)
print("Model loaded successfully from SavedModel format!")
```
**Expected Behavior:**
The model should load successfully from the HDF5 file when `custom_objects` is provided.

**Actual Behavior:**
`ValueError: Unknown layer: 'CustomActivation'`

This kind of detail is a godsend for busy maintainers.

3. Reviewing Pull Requests

If you’re comfortable with the codebase, even a partial understanding, reviewing other people’s PRs is a fantastic way to contribute. You might catch a typo, suggest a clearer variable name, or point out a potential edge case. This helps maintainers by offloading some of their review burden and improves the quality of the incoming code.

4. Answering Questions in Forums/Issues

Many projects have GitHub Discussions, Discord servers, or Stack Overflow tags. If you’ve solved a problem recently, sharing your solution or guiding another user can be immensely helpful. It reduces the support load on maintainers and builds a stronger community.

My Latest Gardening Endeavor: The CI/CD Patch

Just last month, I found myself in another “gardening” situation. I was trying to use an experimental feature in a reinforcement learning library, but the `main` branch was failing its CI tests pretty consistently. The feature worked locally, but the CI failures meant that a new release was unlikely, and anyone building from `main` would hit problems. I dug into the CI logs and realized a dependency had changed its API subtly, causing one of the tests to break.

It wasn’t a core library issue, but a CI configuration problem. I opened an issue, explained what I found, and then offered to submit a PR to fix the CI script. It involved a small change to a `requirements.txt` file and a minor adjustment in a test helper script to accommodate the new API. Again, it wasn’t a flashy feature, but it unblocked the maintainers from releasing new features and made the `main` branch reliable again for everyone. That felt great.

Actionable Takeaways

So, how can you become a more consistent, practical open-source contributor, especially in the AI space?

  • Start small, stay consistent: Don’t wait for the perfect, grand idea. Look for small improvements you can make regularly.
  • Use the tools, report the friction: As you use AI libraries, pay attention to what makes your life harder. Is it unclear documentation? A confusing error message? An outdated example? These are your opportunities.
  • Read the docs, then improve them: If you’re learning a new library, you’re in the perfect position to spot areas where the documentation could be clearer for others.
  • Reproduce, then report: If you hit a bug, dedicate time to create a minimal, reproducible example. It’s a contribution in itself.
  • Engage with the community: Join Discord channels, participate in discussions. Often, you’ll find someone else struggling with the same thing, and solving it together can lead to a direct contribution.
  • Look for “Good First Issues”: Many projects tag issues specifically for new contributors. While these are often small code changes, they’re excellent entry points to understand the contribution workflow.

Open source isn’t just for the original creators or the deep experts. It thrives on the collective efforts of its users and supporters. By adopting a “silent gardener” mindset, focusing on practical, consistent contributions, you can make a real difference in the AI projects you care about, improve your own skills, and become a valued member of the community. Go out there and start planting those seeds!

đź•’ Published:

👨‍💻
Written by Jake Chen

Developer advocate for the OpenClaw ecosystem. Writes tutorials, maintains SDKs, and helps developers ship AI agents faster.

Learn more →
Browse Topics: Architecture | Community | Contributing | Core Development | Customization
Scroll to Top