AI Technical Writer
Automated documentation generation from code, APIs, and technical specifications.
Workflow Steps
- 1
Analyzer Agent examines codebase structure
- 2
Extractor Agent pulls API specs and comments
- 3
Writer Agent generates documentation sections
- 4
Reviewer Agent ensures accuracy and completeness
- 5
Formatter Agent creates final documentation
- 6
Publisher Agent deploys to documentation site
Download
Documentation
AI Technical Writer
Overview
This workflow automates technical documentation generation from codebases, API specifications, and technical documents. It produces comprehensive, accurate documentation including API references, architecture docs, and user guides.
Difficulty
Medium - Requires codebase access and understanding of documentation standards.
Tools Required
- PydanticAI / Claude: Code analysis and documentation generation
- GitHub: Codebase access and version control
- Swagger/OpenAPI: API specification parsing
- MkDocs / Docusaurus: Documentation site generation
- Notion: Documentation storage and collaboration
Workflow Steps
Step 1: Analyzer Agent
Examines codebase structure and patterns.
import os
import ast
from pathlib import Path
from typing import Dict, List, Set
class CodeAnalyzer:
"""
Analyze codebase structure and extract documentation-relevant information.
"""
def __init__(self, repo_path: str):
self.repo_path = Path(repo_path)
self.structure = {}
self.dependencies = {}
self.api_endpoints = []
def analyze(self) -> Dict:
"""
Perform comprehensive codebase analysis.
Returns:
Structured analysis of the codebase
"""
# Get file structure
self.structure = self._get_file_structure()
# Analyze imports and dependencies
self.dependencies = self._analyze_dependencies()
# Extract API endpoints (for web frameworks)
self.api_endpoints = self._extract_api_endpoints()
# Identify key classes and functions
self.public_api = self._extract_public_api()
return {
"structure": self.structure,
"dependencies": self.dependencies,
"api_endpoints": self.api_endpoints,
"public_api": self.public_api,
"tech_stack": self._identify_tech_stack()
}
def _get_file_structure(self) -> Dict:
"""Get the file and directory structure."""
structure = {}
for root, dirs, files in os.walk(self.repo_path):
# Skip hidden directories and common non-code directories
dirs[:] = [d for d in dirs if not d.startswith('.') and d not in
['node_modules', '__pycache__', 'venv', '.git', 'dist', 'build']]
rel_path = os.path.relpath(root, self.repo_path)
if files:
structure[rel_path] = {
"files": files,
"count": len(files)
}
return structure
def _analyze_dependencies(self) -> Dict:
"""Analyze project dependencies."""
dependencies = {
"python": [],
"javascript": [],
"other": []
}
# Python: requirements.txt, pyproject.toml, setup.py
req_files = ['requirements.txt', 'requirements/*.txt']
for req_file in req_files:
for path in self.repo_path.glob(req_file):
if path.exists():
dependencies["python"] = self._parse_requirements(path)
# Python: pyproject.toml
pyproject = self.repo_path / 'pyproject.toml'
if pyproject.exists():
dependencies["python"] = self._parse_pyproject(pyproject)
# JavaScript: package.json
package_json = self.repo_path / 'package.json'
if package_json.exists():
dependencies["javascript"] = self._parse_package_json(package_json)
return dependencies
def _extract_api_endpoints(self) -> List[Dict]:
"""Extract API endpoints from web framework code."""
endpoints = []
# Look for common web framework patterns
for py_file in self.repo_path.rglob('*.py'):
content = py_file.read_text()
# FastAPI patterns
if '@app.' in content or '@router.' in content:
endpoints.extend(self._parse_fastapi(py_file))
# Flask patterns
if '@app.route' in content or '@blueprint.route' in content:
endpoints.extend(self._parse_flask(py_file))
# Django patterns
if 'path(' in content or 'url(' in content:
endpoints.extend(self._parse_django(py_file))
return endpoints
def _parse_fastapi(self, file_path: Path) -> List[Dict]:
"""Parse FastAPI routes."""
endpoints = []
content = file_path.read_text()
# Simple regex-based extraction (would use AST in production)
import re
patterns = [
r'@(app|router)\.(get|post|put|delete|patch)\([\'"]([^\'"]+)[\'"]',
r'@(app|router)\.(api_router)\.add_api_route\([\'"]([^\'"]+)[\'"]'
]
for pattern in patterns:
matches = re.findall(pattern, content)
for match in matches:
endpoints.append({
"method": match[1].upper(),
"path": match[2],
"file": str(file_path.relative_to(self.repo_path))
})
return endpoints
def _extract_public_api(self) -> Dict:
"""Extract public classes and functions."""
public_api = {
"classes": [],
"functions": [],
"modules": []
}
for py_file in self.repo_path.rglob('*.py'):
if py_file.name.startswith('_'):
continue
try:
tree = ast.parse(py_file.read_text())
for node in ast.walk(tree):
if isinstance(node, ast.ClassDef):
if not node.name.startswith('_'):
public_api["classes"].append({
"name": node.name,
"file": str(py_file.relative_to(self.repo_path)),
"methods": [m.name for m in node.body
if isinstance(m, ast.FunctionDef)
and not m.name.startswith('_')]
})
elif isinstance(node, ast.FunctionDef):
if not node.name.startswith('_') and isinstance(node, ast.Module):
public_api["functions"].append({
"name": node.name,
"file": str(py_file.relative_to(self.repo_path)),
"args": [arg.arg for arg in node.args.args]
})
except SyntaxError:
continue
return public_api
def _identify_tech_stack(self) -> Dict:
"""Identify the technology stack."""
stack = {
"languages": [],
"frameworks": [],
"databases": [],
"tools": []
}
# Check for common indicators
files = [f.name for f in self.repo_path.iterdir()]
if 'package.json' in files:
stack["languages"].append("JavaScript/TypeScript")
if any(f.endswith('.py') for f in self.repo_path.rglob('*')):
stack["languages"].append("Python")
# Check for framework indicators
content = ""
for py_file in self.repo_path.rglob('*.py'):
content += py_file.read_text()[:1000]
if 'fastapi' in content.lower():
stack["frameworks"].append("FastAPI")
if 'flask' in content.lower():
stack["frameworks"].append("Flask")
if 'django' in content.lower():
stack["frameworks"].append("Django")
if 'langchain' in content.lower():
stack["frameworks"].append("LangChain")
if 'sqlalchemy' in content.lower():
stack["databases"].append("SQLAlchemy/SQL")
if 'mongodb' in content.lower() or 'pymongo' in content.lower():
stack["databases"].append("MongoDB")
return stack
# Example usage
analyzer = CodeAnalyzer("/path/to/repo")
analysis = analyzer.analyze()
"""
{
"structure": {
"src": {"files": ["__init__.py", "main.py", "api.py"], "count": 3},
"src/api": {"files": ["routes.py", "schemas.py"], "count": 2}
},
"dependencies": {
"python": ["fastapi", "pydantic", "sqlalchemy"],
"javascript": []
},
"api_endpoints": [
{"method": "GET", "path": "/api/users", "file": "src/api/routes.py"},
{"method": "POST", "path": "/api/users", "file": "src/api/routes.py"}
],
"public_api": {
"classes": [{"name": "User", "file": "src/models.py", "methods": ["create", "get", "update"]}],
"functions": []
},
"tech_stack": {
"languages": ["Python"],
"frameworks": ["FastAPI"],
"databases": ["SQLAlchemy"],
"tools": []
}
}
"""
Step 2: Extractor Agent
Pulls API specs and code comments.
import yaml
import json
from openapi_spec_validator import validate
class SpecExtractor:
"""
Extract API specifications and code documentation.
"""
def extract_openapi(self, spec_path: str) -> Dict:
"""
Extract and validate OpenAPI specification.
Args:
spec_path: Path to OpenAPI spec file
Returns:
Validated OpenAPI specification
"""
with open(spec_path, 'r') as f:
if spec_path.endswith('.yaml') or spec_path.endswith('.yml'):
spec = yaml.safe_load(f)
else:
spec = json.load(f)
# Validate spec
try:
validate(spec)
except Exception as e:
print(f"Warning: OpenAPI spec validation failed: {e}")
return {
"openapi": spec.get("openapi", "3.0.0"),
"info": spec.get("info", {}),
"servers": spec.get("servers", []),
"paths": self._extract_paths(spec.get("paths", {})),
"components": spec.get("components", {}),
"tags": spec.get("tags", [])
}
def _extract_paths(self, paths: Dict) -> List[Dict]:
"""Extract detailed path information."""
extracted = []
for path, methods in paths.items():
for method, operation in methods.items():
if method in ['get', 'post', 'put', 'delete', 'patch', 'options', 'head']:
extracted.append({
"path": path,
"method": method.upper(),
"summary": operation.get("summary", ""),
"description": operation.get("description", ""),
"operation_id": operation.get("operationId"),
"tags": operation.get("tags", []),
"parameters": self._extract_parameters(operation.get("parameters", [])),
"request_body": operation.get("requestBody"),
"responses": self._extract_responses(operation.get("responses", {})),
"security": operation.get("security", [])
})
return extracted
def _extract_parameters(self, parameters: List[Dict]) -> List[Dict]:
"""Extract parameter details."""
extracted = []
for param in parameters:
extracted.append({
"name": param.get("name"),
"in": param.get("in"),
"required": param.get("required", False),
"description": param.get("description", ""),
"schema": param.get("schema", {}),
"example": param.get("example")
})
return extracted
def _extract_responses(self, responses: Dict) -> Dict:
"""Extract response details."""
extracted = {}
for status_code, response in responses.items():
extracted[status_code] = {
"description": response.get("description", ""),
"content": response.get("content", {}),
"headers": response.get("headers", {})
}
return extracted
def extract_docstrings(self, code_analysis: Dict) -> List[Dict]:
"""
Extract docstrings from codebase.
Args:
code_analysis: Output from CodeAnalyzer
Returns:
List of documented classes and functions
"""
docstrings = []
for cls in code_analysis["public_api"]["classes"]:
docstrings.append({
"type": "class",
"name": cls["name"],
"file": cls["file"],
"methods": cls["methods"]
})
for func in code_analysis["public_api"]["functions"]:
docstrings.append({
"type": "function",
"name": func["name"],
"file": func["file"],
"args": func["args"]
})
return docstrings
# Example usage
extractor = SpecExtractor()
api_spec = extractor.extract_openapi("docs/openapi.yaml")
docstrings = extractor.extract_docstrings(analysis)
Step 3: Writer Agent
Generates documentation sections.
class DocumentationWriter:
"""
Generate documentation from code analysis and API specs.
"""
def generate_documentation(self, analysis: Dict, api_spec: Dict,
docstrings: List[Dict], config: Dict) -> Dict:
"""
Generate comprehensive documentation.
Args:
analysis: Codebase analysis
api_spec: API specification
docstrings: Extracted docstrings
config: Documentation configuration
Returns:
Generated documentation sections
"""
docs = {
"overview": self._generate_overview(analysis, config),
"installation": self._generate_installation(analysis),
"quickstart": self._generate_quickstart(analysis, config),
"api_reference": self._generate_api_reference(api_spec),
"architecture": self._generate_architecture(analysis),
"examples": self._generate_examples(analysis, config),
"contributing": self._generate_contributing(config)
}
return docs
def _generate_overview(self, analysis: Dict, config: Dict) -> str:
"""Generate project overview."""
prompt = f"""
Write a comprehensive project overview for documentation.
Project Information:
- Tech Stack: {analysis['tech_stack']}
- Structure: {len(analysis['structure'])} directories, {sum(f['count'] for f in analysis['structure'].values())} files
- API Endpoints: {len(analysis['api_endpoints'])}
- Public Classes: {len(analysis['public_api']['classes'])}
- Public Functions: {len(analysis['public_api']['functions'])}
Project Name: {config.get('project_name', 'This Project')}
Description: {config.get('description', 'A comprehensive documentation project')}
Write a 3-4 paragraph overview covering:
1. What the project does
2. Key features and capabilities
3. Target audience and use cases
4. Architecture highlights
Tone: Professional, clear, accessible to developers
"""
return call_claude(prompt)
def _generate_installation(self, analysis: Dict) -> str:
"""Generate installation instructions."""
deps = analysis.get("dependencies", {})
installation = "## Installation\n\n"
if deps.get("python"):
installation += "### Python\n\n"
installation += "```bash\n"
installation += "pip install " + " ".join(deps["python"]) + "\n"
installation += "```\n\n"
if deps.get("javascript"):
installation += "### JavaScript/TypeScript\n\n"
installation += "```bash\n"
installation += "npm install " + " ".join(deps["javascript"]) + "\n"
installation += "```\n\n"
installation += "### From Source\n\n"
installation += "```bash\n"
installation += "git clone https://github.com/user/repo.git\n"
installation += "cd repo\n"
installation += "pip install -e .\n"
installation += "```\n"
return installation
def _generate_quickstart(self, analysis: Dict, config: Dict) -> str:
"""Generate quickstart guide."""
prompt = f"""
Write a quickstart guide for {config.get('project_name', 'this project')}.
Key Features:
- {len(analysis['api_endpoints'])} API endpoints
- {len(analysis['public_api']['classes'])} main classes
Include:
1. Minimal working example (5-10 lines of code)
2. Explanation of what the code does
3. Expected output
Keep it simple and actionable.
"""
return call_claude(prompt)
def _generate_api_reference(self, api_spec: Dict) -> str:
"""Generate API reference from OpenAPI spec."""
api_ref = "# API Reference\n\n"
# Group by tags
tags = api_spec.get("tags", [])
paths = api_spec.get("paths", [])
for tag in tags:
api_ref += f"## {tag['name']}\n\n"
if tag.get("description"):
api_ref += f"{tag['description']}\n\n"
# Find endpoints for this tag
tag_endpoints = [p for p in paths if tag['name'] in p.get('tags', [])]
for endpoint in tag_endpoints:
api_ref += f"### {endpoint['method']} {endpoint['path']}\n\n"
if endpoint.get('summary'):
api_ref += f"**{endpoint['summary']}**\n\n"
if endpoint.get('description'):
api_ref += f"{endpoint['description']}\n\n"
# Parameters
if endpoint.get('parameters'):
api_ref += "**Parameters:**\n\n"
api_ref += "| Name | In | Required | Description |\n"
api_ref += "|------|-----|----------|-------------|\n"
for param in endpoint['parameters']:
api_ref += f"| {param['name']} | {param['in']} | {'Yes' if param['required'] else 'No'} | {param.get('description', '')} |\n"
api_ref += "\n"
# Responses
if endpoint.get('responses'):
api_ref += "**Responses:**\n\n"
for status, response in endpoint['responses'].items():
api_ref += f"- **{status}**: {response.get('description', '')}\n"
api_ref += "\n"
return api_ref
def _generate_architecture(self, analysis: Dict) -> str:
"""Generate architecture documentation."""
prompt = f"""
Write architecture documentation based on this codebase analysis.
Structure:
{json.dumps(analysis['structure'], indent=2)}
Tech Stack:
{json.dumps(analysis['tech_stack'], indent=2)}
Include:
1. High-level architecture overview
2. Directory structure explanation
3. Key components and their responsibilities
4. Data flow diagram description
Use mermaid diagrams where appropriate.
"""
return call_claude(prompt)
def _generate_examples(self, analysis: Dict, config: Dict) -> str:
"""Generate code examples."""
prompt = f"""
Generate practical code examples for {config.get('project_name', 'this project')}.
Public API:
- Classes: {analysis['public_api']['classes']}
- Functions: {analysis['public_api']['functions']}
Create 3-5 examples:
1. Basic usage
2. Common use case
3. Advanced feature
Each example should be complete, runnable code with comments.
"""
return call_claude(prompt)
# Example usage
writer = DocumentationWriter()
docs = writer.generate_documentation(analysis, api_spec, docstrings, {
"project_name": "MyAPI",
"description": "A modern REST API for managing resources"
})
Step 4: Reviewer Agent
Ensures accuracy and completeness.
class DocReviewer:
"""
Review and validate generated documentation.
"""
def review(self, docs: Dict, analysis: Dict, api_spec: Dict) -> Dict:
"""
Review documentation for accuracy and completeness.
Args:
docs: Generated documentation
analysis: Codebase analysis
api_spec: API specification
Returns:
Review results with suggestions
"""
review = {
"accuracy": self._check_accuracy(docs, analysis, api_spec),
"completeness": self._check_completeness(docs, analysis),
"consistency": self._check_consistency(docs),
"clarity": self._check_clarity(docs),
"suggestions": []
}
# Generate improvement suggestions
review["suggestions"] = self._generate_suggestions(review)
return review
def _check_accuracy(self, docs: Dict, analysis: Dict, api_spec: Dict) -> Dict:
"""Check documentation accuracy against source."""
issues = []
# Verify API endpoints match
doc_endpoints = self._extract_documented_endpoints(docs.get("api_reference", ""))
actual_endpoints = api_spec.get("paths", [])
for endpoint in actual_endpoints:
if endpoint not in doc_endpoints:
issues.append({
"type": "missing_endpoint",
"severity": "high",
"message": f"Endpoint {endpoint['method']} {endpoint['path']} not documented"
})
# Verify class/function documentation
for cls in analysis["public_api"]["classes"]:
if cls["name"] not in docs.get("api_reference", ""):
issues.append({
"type": "missing_class",
"severity": "medium",
"message": f"Class {cls['name']} not documented"
})
return {
"passed": len([i for i in issues if i["severity"] == "high"]) == 0,
"issues": issues
}
def _check_completeness(self, docs: Dict, analysis: Dict) -> Dict:
"""Check documentation completeness."""
required_sections = ["overview", "installation", "quickstart", "api_reference"]
missing = [s for s in required_sections if s not in docs or not docs[s]]
return {
"passed": len(missing) == 0,
"missing_sections": missing
}
def _check_consistency(self, docs: Dict) -> Dict:
"""Check documentation consistency."""
issues = []
# Check for consistent terminology
terms = self._extract_key_terms(docs)
for term, variations in terms.items():
if len(variations) > 1:
issues.append({
"type": "inconsistent_terminology",
"severity": "low",
"message": f"Term '{term}' used as: {', '.join(variations)}"
})
return {
"passed": len([i for i in issues if i["severity"] == "high"]) == 0,
"issues": issues
}
def _check_clarity(self, docs: Dict) -> Dict:
"""Check documentation clarity."""
prompt = f"""
Review this documentation for clarity and readability.
Documentation:
{str(docs)[:3000]}
Evaluate:
1. Is the language clear and accessible?
2. Are technical terms explained?
3. Is the structure logical?
4. Are examples helpful?
Provide specific suggestions for improvement.
"""
feedback = call_claude(prompt)
return {
"feedback": feedback,
"readability_score": self._estimate_readability(docs)
}
def _generate_suggestions(self, review: Dict) -> List[str]:
"""Generate improvement suggestions."""
suggestions = []
for section, result in review.items():
if isinstance(result, dict) and result.get("issues"):
for issue in result["issues"]:
suggestions.append(f"[{issue['severity'].upper()}] {issue['message']}")
return suggestions
# Example review
reviewer = DocReviewer()
review = reviewer.review(docs, analysis, api_spec)
"""
{
"accuracy": {
"passed": true,
"issues": []
},
"completeness": {
"passed": true,
"missing_sections": []
},
"consistency": {
"passed": true,
"issues": [
{"type": "inconsistent_terminology", "severity": "low", "message": "Term 'endpoint' used as: API endpoint, endpoint, route"}
]
},
"clarity": {
"feedback": "Documentation is clear and well-structured. Consider adding more examples for advanced features.",
"readability_score": 85
},
"suggestions": [
"[LOW] Term 'endpoint' used as: API endpoint, endpoint, route"
]
}
"""
Step 5: Formatter Agent
Creates final documentation.
class DocumentationFormatter:
"""
Format documentation for different output formats.
"""
def format(self, docs: Dict, review: Dict, config: Dict) -> Dict:
"""
Format documentation for output.
Args:
docs: Generated documentation
review: Review results
config: Formatting configuration
Returns:
Formatted documentation files
"""
outputs = {}
if config.get("format") == "mkdocs":
outputs = self._format_mkdocs(docs, review, config)
elif config.get("format") == "docusaurus":
outputs = self._format_docusaurus(docs, review, config)
elif config.get("format") == "notion":
outputs = self._format_notion(docs, review, config)
elif config.get("format") == "markdown":
outputs = self._format_markdown(docs, review, config)
return outputs
def _format_mkdocs(self, docs: Dict, review: Dict, config: Dict) -> Dict:
"""Format for MkDocs."""
outputs = {}
# mkdocs.yml
outputs["mkdocs.yml"] = f"""
site_name: {config.get('project_name', 'Documentation')}
site_description: {config.get('description', 'Project documentation')}
theme:
name: material
palette:
- media: "(prefers-color-scheme)"
toggle:
icon: material/brightness-auto
name: Switch to light mode
- media: "(prefers-color-scheme: light)"
scheme: default
toggle:
icon: material/brightness-7
name: Switch to dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
toggle:
icon: material/brightness-4
name: Switch to system preference
nav:
- Home: index.md
- Getting Started:
- Installation: installation.md
- Quickstart: quickstart.md
- API Reference: api_reference.md
- Architecture: architecture.md
- Examples: examples.md
- Contributing: contributing.md
plugins:
- search
- mkdocstrings
markdown_extensions:
- admonition
- codehilite
- pymdownx.highlight
- pymdownx.superfences
- pymdownx.tabbed
"""
# index.md
outputs["docs/index.md"] = f"""# {config.get('project_name', 'Documentation')}
{docs.get('overview', '')}
## Quick Links
- [Installation](installation.md)
- [Quickstart Guide](quickstart.md)
- [API Reference](api_reference.md)
"""
# Other pages
for section, content in docs.items():
if section not in ["overview"]:
outputs[f"docs/{section}.md"] = content
return outputs
def _format_markdown(self, docs: Dict, review: Dict, config: Dict) -> Dict:
"""Format as standalone Markdown files."""
outputs = {}
outputs["README.md"] = f"""# {config.get('project_name', 'Documentation')}
{docs.get('overview', '')}
## Installation
{docs.get('installation', '')}
## Quickstart
{docs.get('quickstart', '')}
## API Reference
{docs.get('api_reference', '')}
## Architecture
{docs.get('architecture', '')}
## Examples
{docs.get('examples', '')}
## Contributing
{docs.get('contributing', '')}
---
*Generated by AI Technical Writer*
"""
return outputs
# Example formatting
formatter = DocumentationFormatter()
outputs = formatter.format(docs, review, {
"project_name": "MyAPI",
"description": "A modern REST API",
"format": "mkdocs"
})
Step 6: Publisher Agent
Deploys documentation.
class DocumentationPublisher:
"""
Publish documentation to various platforms.
"""
def publish(self, outputs: Dict, config: Dict) -> Dict:
"""
Publish documentation.
Args:
outputs: Formatted documentation files
config: Publishing configuration
Returns:
Publishing results
"""
results = {}
if config.get("deploy_to") == "github_pages":
results = self._deploy_github_pages(outputs, config)
elif config.get("deploy_to") == "netlify":
results = self._deploy_netlify(outputs, config)
elif config.get("deploy_to") == "notion":
results = self._deploy_notion(outputs, config)
return results
def _deploy_github_pages(self, outputs: Dict, config: Dict) -> Dict:
"""Deploy to GitHub Pages."""
import subprocess
# Clone docs repo or use existing
repo_url = config.get("repo_url")
# Create gh-pages branch if needed
subprocess.run(["git", "checkout", "gh-pages"], capture_output=True)
# Write files
for path, content in outputs.items():
file_path = Path(path)
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(content)
# Commit and push
subprocess.run(["git", "add", "."], capture_output=True)
subprocess.run(["git", "commit", "-m", "Update documentation"], capture_output=True)
subprocess.run(["git", "push", "origin", "gh-pages"], capture_output=True)
return {
"success": True,
"url": f"https://{config.get('github_user', 'user')}.github.io/{config.get('repo_name', 'docs')}",
"deployed_at": datetime.utcnow().isoformat()
}
def _deploy_notion(self, outputs: Dict, config: Dict) -> Dict:
"""Publish to Notion."""
from notion_client import Client
notion = Client(auth=config["notion_token"])
parent_page_id = config["parent_page_id"]
created_pages = []
for filename, content in outputs.items():
# Parse markdown to Notion blocks
blocks = self._markdown_to_notion_blocks(content)
page = notion.pages.create(
parent={"page_id": parent_page_id},
properties={
"title": [{"text": {"content": Path(filename).stem.replace("-", " ").title()}}]
},
children=blocks
)
created_pages.append(page["id"])
return {
"success": True,
"pages": created_pages,
"deployed_at": datetime.utcnow().isoformat()
}
# Example publishing
publisher = DocumentationPublisher()
results = publisher.publish(outputs, {
"deploy_to": "github_pages",
"repo_url": "https://github.com/user/docs",
"github_user": "user",
"repo_name": "docs"
})
Example Usage
# Documentation generation workflow
1. Analyzer: Scan 500+ files, extract 45 endpoints, 120 classes (2 min)
2. Extractor: Parse OpenAPI spec, extract docstrings (1 min)
3. Writer: Generate 8 documentation sections (3 min)
4. Reviewer: Check accuracy, completeness, consistency (1 min)
5. Formatter: Create MkDocs structure (30 sec)
6. Publisher: Deploy to GitHub Pages (1 min)
# Total: ~8 minutes, fully automated
Pros
- ✅ Generates comprehensive documentation automatically
- ✅ Ensures documentation matches actual code
- ✅ Consistent formatting and style
- ✅ Supports multiple output formats
- ✅ Saves hours of manual documentation work
Cons
- ❌ Generated docs need human review for quality
- ❌ May miss nuanced documentation needs
- ❌ Code changes require regeneration
- ❌ Complex codebases may produce overwhelming docs
- ❌ AI may generate inaccurate technical details
When to Use
Use this workflow when:
- You need to generate docs for a new codebase
- Your documentation is outdated or incomplete
- You want consistent documentation across projects
- You need to document APIs quickly
Consider alternatives when:
- You have a small, simple codebase
- Your team has strong documentation practices
- Documentation requires deep domain expertise
- You need interactive API documentation (use Swagger UI directly)
