Using IBM Bob SDLC in documentation mode.
Introduction
In the fast-paced world of software development, it is easy to pigeonhole an AI assistant like IBM Bob SDLC as just another code-crunching engine. While its ability to churn out clean, efficient syntax is undeniable, its true value lies in its versatility across the entire project lifecycle. Whether you are a junior developer looking to bridge the gap between logic and implementation, or a Product Owner, Functional Consultant, or Project Manager navigating the complexities of requirements, Bob adapts to your needs. From drafting comprehensive technical specifications to performing the “detective work” of retro-documentation on legacy systems, IBM Bob is less of a simple tool and more of a multi-faceted collaborator designed to streamline workflows for every stakeholder involved.
To illustrate this, let’s jump into a hypothetical case of retro documentation of a whole application based on a code repository (a GitHub repository). I asked candidly from Bob to provide a detailed an architecture documentation for the IBM Instana Go-Sensor code! And Bob did it for sure 🤓 (even though the code is well documented), but my aim is to showcase one of the document writing capacities of Bob!
TL;DR-What is Instana?
Instana STAN
At its core, IBM Instana is an enterprise-grade observability and Application Performance Monitoring (APM) platform designed for the complexity of modern, cloud-native environments. Unlike traditional monitoring tools that require manual configuration and struggle with the ephemeral nature of microservices, Instana is built on automation. It utilizes “Agentic AI” and over 250 domain-specific sensors to automatically discover, map, and monitor every component of your technology stack — from mobile front-ends and web browsers down to the underlying infrastructure, including Kubernetes, serverless functions, and even legacy mainframes.

It captures high-fidelity data with one-second granularity and traces every single request without sampling, ensuring that no performance anomaly or error goes unnoticed. By leveraging AI-powered root-cause analysis, Instana doesn’t just alert you that something is wrong; it correlates events to tell you why it happened, drastically reducing the Mean Time to Repair (MTTR). This “democratization of data” allows DevOps, SREs, and Product Owners to move away from reactive “war rooms” and toward proactive optimization, ensuring a seamless and reliable end-user experience across the entire digital journey.
When Bob meets Stan 😂
OK, having introduced Instana, for my test usecase, I gave the following prompt to Bob, and then I show the interactions between Bob and myself!
Read the following Github: https://github.com/instana/go-sensor and provide a full arhitectural document of the repository and waht the code does alongside with mermaid flow charts
I want the architecture mermaid flow charts added as well
- Then a whole task list is provided, the user can always stop Bob and give further instructions;
- Once I validated the tasks (or if you authorize Bob to do specific tasks without approval for all steps…), I got a full architecture document in Markdown format, with revelant flows and a detailed documentation. The one shown below is the high-level architecture schema.
- There are also several specific area flows provided.
The document contains also description of components and in this case a recap table of “Framework Instrumentation Packages”.
Framework Instrumentation Packages
| Package | Framework | Features |
| -------------------- | ---------------- | --------------------------- |
| `instagin` | Gin | Middleware for HTTP routing |
| `instaecho` | Echo | HTTP middleware |
| `instafiber` | Fiber | HTTP middleware |
| `instamux` | Gorilla Mux | HTTP middleware |
| `instabeego` | Beego | HTTP middleware |
| `instafasthttp` | FastHTTP | HTTP middleware |
| `instagrpc` | gRPC | Unary & stream interceptors |
| `instasarama` | Kafka (Sarama) | Producer/consumer wrappers |
| `instaamqp091` | RabbitMQ | Publisher/consumer wrappers |
| `instamongo` | MongoDB | Command monitoring |
| `instaredis` | Redis (go-redis) | Command hooks |
| `instaredigo` | Redis (Redigo) | Connection wrapper |
| `instagorm` | GORM | Callbacks for DB operations |
| `instagocb` | Couchbase | Bucket wrapper |
| `instapgx` | PostgreSQL (pgx) | Tracer implementation |
| `instacosmos` | Azure Cosmos DB | Client wrapper |
| `instaawssdk` | AWS SDK v1 | Service handlers |
| `instaawsv2` | AWS SDK v2 | Middleware |
| `instalambda` | AWS Lambda | Handler wrapper |
| `instaazurefunction` | Azure Functions | Handler wrapper |
| `instagraphql` | GraphQL | Resolver middleware |
Bob can also provide a documentation on specific part or parts of an existing code. Let’s imagine that hypothetically we have an undocumented code or a code in a programming language we do not know!
// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2020
package instana
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strconv"
"sync"
"time"
"github.com/instana/go-sensor/acceptor"
"github.com/instana/go-sensor/autoprofile"
)
const awsLambdaAgentFlushPeriod = 2 * time.Second
type lambdaAgent struct {
Endpoint string
Key string
PID int
snapshot serverlessSnapshot
mu sync.RWMutex
spanQueue []Span
client *http.Client
logger LeveledLogger
}
func newLambdaAgent(
serviceName, acceptorEndpoint, agentKey string,
client *http.Client,
logger LeveledLogger,
) *lambdaAgent {
if logger == nil {
logger = defaultLogger
}
if client == nil {
client = http.DefaultClient
}
logger.Debug("initializing aws lambda agent")
agent := &lambdaAgent{
Endpoint: acceptorEndpoint,
Key: agentKey,
PID: os.Getpid(),
client: client,
logger: logger,
}
go func(a *lambdaAgent) {
t := time.NewTicker(awsLambdaAgentFlushPeriod)
defer t.Stop()
for range t.C {
if err := a.Flush(context.Background()); err != nil {
a.logger.Error("failed to post collected data: ", err)
}
}
}(agent)
return agent
}
func (a *lambdaAgent) Ready() bool { return true }
func (a *lambdaAgent) SendMetrics(data acceptor.Metrics) error { return nil }
func (a *lambdaAgent) SendEvent(event *EventData) error { return nil }
func (a *lambdaAgent) SendSpans(spans []Span) error {
a.enqueueSpans(spans)
return nil
}
func (a *lambdaAgent) SendProfiles(profiles []autoprofile.Profile) error { return nil }
func (a *lambdaAgent) Flush(ctx context.Context) error {
snapshot := a.collectSnapshot(a.spanQueue)
if snapshot.EntityID == "" {
return ErrAgentNotReady
}
from := newServerlessAgentFromS(snapshot.EntityID, "aws")
payload := struct {
Metrics metricsPayload `json:"metrics,omitempty"`
Spans []Span `json:"spans,omitempty"`
}{
Metrics: metricsPayload{
Plugins: []acceptor.PluginPayload{
acceptor.NewAWSLambdaPluginPayload(snapshot.EntityID),
},
},
}
a.mu.Lock()
payload.Spans = make([]Span, len(a.spanQueue))
copy(payload.Spans, a.spanQueue)
a.spanQueue = a.spanQueue[:0]
a.mu.Unlock()
for i := range payload.Spans {
payload.Spans[i].From = from
}
buf := bytes.NewBuffer(nil)
if err := json.NewEncoder(buf).Encode(payload); err != nil {
return fmt.Errorf("failed to marshal traces payload: %s", err)
}
req, err := http.NewRequest(http.MethodPost, a.Endpoint+"/bundle", buf)
if err != nil {
a.enqueueSpans(payload.Spans)
return fmt.Errorf("failed to prepare send traces request: %s", err)
}
req.Header.Set("Content-Type", "application/json")
if err := a.sendRequest(req.WithContext(ctx)); err != nil {
a.enqueueSpans(payload.Spans)
return fmt.Errorf("failed to send traces, will retry later: %s", err)
}
return nil
}
func (a *lambdaAgent) enqueueSpans(spans []Span) {
a.mu.Lock()
defer a.mu.Unlock()
a.spanQueue = append(a.spanQueue, spans...)
}
func (a *lambdaAgent) sendRequest(req *http.Request) error {
a.mu.RLock()
host := a.snapshot.Host
a.mu.RUnlock()
req.Header.Set("X-Instana-Host", host)
req.Header.Set("X-Instana-Key", a.Key)
req.Header.Set("X-Instana-Time", strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10))
resp, err := a.client.Do(req)
if err != nil {
return fmt.Errorf("failed to send request to the serverless agent: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode >= http.StatusBadRequest {
respBody, err := io.ReadAll(resp.Body)
if err != nil {
a.logger.Debug("failed to read serverless agent response: ", err)
return nil
}
a.logger.Info("serverless agent has responded with ", resp.Status, ": ", string(respBody))
return nil
}
io.CopyN(io.Discard, resp.Body, 1<<20)
return nil
}
func (a *lambdaAgent) collectSnapshot(spans []Span) serverlessSnapshot {
a.mu.RLock()
entityID := a.snapshot.EntityID
a.mu.RUnlock()
if entityID != "" {
return a.snapshot
}
// searching for the lambda entry span in reverse order, since it's
// more likely to be finished last
for i := len(spans) - 1; i >= 0; i-- {
sp, ok := spans[i].Data.(AWSLambdaSpanData)
if !ok {
continue
}
a.mu.Lock()
a.snapshot = serverlessSnapshot{
EntityID: sp.Snapshot.ARN,
Host: sp.Snapshot.ARN,
}
a.mu.Unlock()
a.logger.Debug("collected snapshot")
break
}
return a.snapshot
}
- I gave the following prompt to Bob ⤵️
Provide a document explainig the "lambda_agent.go" functionality, what it does and how it can be used
- Not only Bob provides the very detailed documentation, but also a full detailed component architecture of tho code! I provide hereafter a portion of the document generated.
-Core Components
The Lambda agent consists of several key components:
1. **Span Queue**: Thread-safe buffer for collecting trace spans
2. **Snapshot Collector**: Captures Lambda function metadata (ARN, version, etc.)
3. **Periodic Flusher**: Automatically sends data every 2 seconds
4. **HTTP Client**: Handles communication with Instana backend
-Key Features
-1. Automatic Span Collection
The agent automatically collects and queues trace spans generated during Lambda execution:
- **Thread-safe queuing**: Uses mutex locks to prevent race conditions
- **Automatic batching**: Groups spans for efficient transmission
- **Retry mechanism**: Re-queues spans if sending fails
-2. Serverless Snapshot
Captures essential Lambda function metadata:
- **ARN (Amazon Resource Name)**: Unique identifier for the Lambda function
- **Host information**: Lambda execution environment details
- **Process ID**: Current Lambda container process
-3. Periodic Flushing
Automatically sends collected data at regular intervals:
- **Flush period**: 2 seconds (configurable via `awsLambdaAgentFlushPeriod`)
- **Background goroutine**: Non-blocking operation
- **Context-aware**: Respects cancellation and timeouts
-4. Metrics Integration
Includes AWS Lambda plugin payload with each flush:
- **Entity identification**: Links spans to Lambda function
- **Cloud provider metadata**: AWS-specific information
- **Performance metrics**: Execution time, cold starts, etc.
-Snapshot Collection
The agent extracts Lambda metadata from the first `aws.lambda.entry` span:
1. Searches span queue in reverse order (most recent first)
2. Finds span with `AWSLambdaSpanData` type
3. Extracts ARN from span snapshot
4. Caches snapshot for subsequent flushes
-Configuration
-Environment Variables
The Lambda agent is automatically configured when running in AWS Lambda environment:
| Variable | Description | Required | Default |
| ---------------------- | ---------------------------------- | -------- | ------- |
| `INSTANA_AGENT_KEY` | Instana backend authentication key | Yes | - |
| `INSTANA_ENDPOINT_URL` | Instana backend endpoint | Yes | - |
| `AWS_EXECUTION_ENV` | AWS Lambda execution environment | Auto-set | - |
| `INSTANA_ZONE` | Availability zone tag | No | - |
| `INSTANA_TAGS` | Custom tags (comma-separated) | No | - |
| `INSTANA_SECRETS` | Secret patterns to redact | No | - |
Conclusion
Ultimately, the integration of IBM Bob SDLC into the analysis of a public repository demonstrates that its value extends far beyond the IDE. By processing the raw complexity of an existing codebase, Bob acts as a bridge between technical debt and clarity. In this specific scenario, its ability to generate retro-documentation — essentially reverse-engineering the “why” behind the “what” — allows teams to reclaim lost knowledge without manual archeology. When paired with application architecture mapping and granular code documentation, Bob transforms a dense thicket of files into a transparent, navigable roadmap.
This synergy proves that Bob is an essential asset for more than just the engineering team. For the Product Owner or Project Manager, these documentation capabilities provide a high-level view of system dependencies and health; for the Functional Consultant, they offer a clear understanding of logic flows. By automating the most tedious aspects of the SDLC, Bob ensures that whether you are onboarding a new junior developer or planning a massive architectural migration, the “source of truth” is always documented, up-to-date, and accessible to everyone involved.
>>> Thanks for reading <<<
Links
- IBM Bob: https://bob.ibm.com/
- Instana: https://www.ibm.com/products/instana
- Instana GitHub Repository: https://github.com/instana











Top comments (0)