everything-gemini 1.2.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug_report.md +29 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +27 -0
- package/.github/ISSUE_TEMPLATE/subagent_proposal.md +29 -0
- package/.github/workflows/ci.yml +72 -1
- package/.github/workflows/release.yml +17 -2
- package/CHANGELOG.md +178 -0
- package/CONTRIBUTING.md +90 -4
- package/README.md +147 -23
- package/action.yml +35 -0
- package/agents/browser-qa.md +1 -1
- package/agents/database-migrator.md +26 -0
- package/agents/documentation-writer.md +27 -0
- package/agents/incident-responder.md +34 -0
- package/agents/performance-tuner.md +27 -0
- package/agents/platform-engineer.md +33 -0
- package/agents/release-engineer.md +34 -0
- package/bin/everything-gemini +1791 -142
- package/docs/COMMUNITY_SUBMISSIONS.md +88 -0
- package/docs/LAUNCH_KIT.md +138 -13
- package/docs/architecture/progressive-disclosure.md +3 -3
- package/docs/index.html +410 -40
- package/docs/launch-kit.md +163 -0
- package/examples/cli-workflows/demo_workflow.sh +15 -7
- package/examples/python-sdk/README.md +32 -5
- package/examples/python-sdk/documentation_audit_pipeline.py +83 -0
- package/examples/python-sdk/incident_triage_pipeline.py +170 -0
- package/examples/python-sdk/multi_agent_pipeline.py +95 -0
- package/examples/python-sdk/platform_provisioning_pipeline.py +193 -0
- package/examples/python-sdk/release_readiness_audit.py +144 -0
- package/hooks/secret-scrubber/hooks.json +16 -0
- package/hooks/secret-scrubber/scripts/scrub-secrets.sh +62 -0
- package/mcp/README.md +21 -0
- package/mcp/mcp_config.example.json +39 -0
- package/package.json +3 -1
- package/plugins/core/rules/core-practices.md +63 -4
- package/plugins/python-ai/rules/ai-agent-patterns.md +67 -4
- package/plugins/security-shield/rules/zero-trust.md +60 -4
- package/plugins/web-fullstack/rules/frontend-standards.md +74 -4
- package/rules/paradigms/security-hardened.md +53 -10
- package/rules/paradigms/tdd.md +65 -8
- package/scripts/install.ps1 +14 -0
- package/scripts/install.sh +15 -1
- package/scripts/validate.sh +103 -12
- package/skills/apache-kafka-streams/SKILL.md +152 -0
- package/skills/argo-workflows/SKILL.md +151 -0
- package/skills/axum-web-service/SKILL.md +159 -0
- package/skills/cilium-ebpf-networking/SKILL.md +145 -0
- package/skills/clickhouse-analytics/SKILL.md +128 -0
- package/skills/cloudflare-r2-object-storage/SKILL.md +143 -0
- package/skills/dbt-transformation/SKILL.md +179 -0
- package/skills/debezium-cdc/SKILL.md +166 -0
- package/skills/distributed-rate-limiting/SKILL.md +138 -0
- package/skills/duckdb-local-olap/SKILL.md +134 -0
- package/skills/fastapi-production/SKILL.md +157 -0
- package/skills/grpc-connect-rpc/SKILL.md +176 -0
- package/skills/langgraph-orchestrator/SKILL.md +144 -0
- package/skills/litellm-proxy-gateway/SKILL.md +154 -0
- package/skills/milvus-vector-clustering/SKILL.md +134 -0
- package/skills/nats-jetstream/SKILL.md +122 -0
- package/skills/open-telemetry-tracing/SKILL.md +151 -0
- package/skills/playwright-visual-regression/SKILL.md +124 -0
- package/skills/redis-cache-patterns/SKILL.md +159 -0
- package/skills/svelte-kit-architect/SKILL.md +190 -0
- package/skills/temporal-workflows/SKILL.md +158 -0
- package/skills/trpc-react-query/SKILL.md +169 -0
- package/skills/turborepo-monorepo/SKILL.md +199 -0
- package/skills/vault-secrets-management/SKILL.md +129 -0
- package/skills/vllm-inference/SKILL.md +144 -0
- package/skills/wasm-rust-optimizer/SKILL.md +130 -0
- package/templates/full-power/hooks.json +14 -0
- package/templates/full-power/mcp_config.json +47 -0
- package/templates/recommended/hooks.json +14 -0
- package/tests/cli.test.js +447 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: duckdb-local-olap
|
|
3
|
+
description: >-
|
|
4
|
+
Architects, queries, and optimizes embedded in-process DuckDB analytical workflows, direct Parquet/S3 querying, zero-copy Apache Arrow dataframes, and MotherDuck hybrid cloud execution.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# DuckDB Local OLAP & Serverless Analytics
|
|
8
|
+
|
|
9
|
+
This skill guides building high-speed analytical engines using DuckDB—the "SQLite for analytics"—enabling columnar vectorized execution, direct querying of compressed Parquet files on cloud storage, and zero-copy transfers with Apache Arrow.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## ⚡ Core Patterns
|
|
14
|
+
|
|
15
|
+
### 1. Direct Parquet Querying Over S3 Without Ingestion
|
|
16
|
+
|
|
17
|
+
Query gigabytes of remote compressed files with projection and predicate pushdowns (only requested byte ranges are transferred over the network):
|
|
18
|
+
|
|
19
|
+
```sql
|
|
20
|
+
-- 1. Install and load HTTP and S3 extensions
|
|
21
|
+
INSTALL httpfs;
|
|
22
|
+
LOAD httpfs;
|
|
23
|
+
|
|
24
|
+
-- 2. Configure S3 authentication
|
|
25
|
+
SET s3_region = 'us-east-1';
|
|
26
|
+
SET s3_access_key_id = 'YOUR_ACCESS_KEY';
|
|
27
|
+
SET s3_secret_access_key = 'YOUR_SECRET_KEY';
|
|
28
|
+
|
|
29
|
+
-- 3. Query remote Parquet directory with globs
|
|
30
|
+
SELECT
|
|
31
|
+
country,
|
|
32
|
+
count(*) AS total_transactions,
|
|
33
|
+
round(avg(amount_usd), 2) AS avg_amount,
|
|
34
|
+
quantile_cont(amount_usd, 0.95) AS p95_amount
|
|
35
|
+
FROM read_parquet('s3://my-data-lake/transactions/year=2026/month=*/*.parquet')
|
|
36
|
+
WHERE status = 'settled'
|
|
37
|
+
GROUP BY country
|
|
38
|
+
ORDER BY total_transactions DESC
|
|
39
|
+
LIMIT 20;
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
### 2. Zero-Copy Python & Polars / Arrow Integration
|
|
45
|
+
|
|
46
|
+
Pass memory buffers directly between DuckDB's vectorized engine and Polars or PyArrow without JSON or IPC serialization:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import duckdb
|
|
50
|
+
import polars as pl
|
|
51
|
+
|
|
52
|
+
# Connect to in-memory instance
|
|
53
|
+
con = duckdb.connect()
|
|
54
|
+
|
|
55
|
+
# Set aggressive memory limits and worker threads
|
|
56
|
+
con.execute("SET memory_limit = '8GB';")
|
|
57
|
+
con.execute("SET threads = 8;")
|
|
58
|
+
|
|
59
|
+
# Create a sample Polars DataFrame
|
|
60
|
+
df = pl.DataFrame({
|
|
61
|
+
"user_id": [101, 102, 103],
|
|
62
|
+
"scores": [98.5, 76.2, 89.0]
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
# Query Polars DataFrame directly as a virtual table (zero-copy)
|
|
66
|
+
arrow_table = con.execute("""
|
|
67
|
+
SELECT
|
|
68
|
+
user_id,
|
|
69
|
+
scores,
|
|
70
|
+
CASE WHEN scores >= 90 THEN 'A' ELSE 'B' END AS grade
|
|
71
|
+
FROM df
|
|
72
|
+
WHERE scores > 80
|
|
73
|
+
""").arrow()
|
|
74
|
+
|
|
75
|
+
# Convert back to Polars instantaneously
|
|
76
|
+
result_df = pl.from_arrow(arrow_table)
|
|
77
|
+
print(result_df)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### 3. Node.js Embedded Analytics Engine
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { Database } from 'duckdb-async';
|
|
86
|
+
|
|
87
|
+
export async function aggregateLocalParquet(parquetPath: string) {
|
|
88
|
+
const db = await Database.create(':memory:');
|
|
89
|
+
|
|
90
|
+
const rows = await db.all(`
|
|
91
|
+
SELECT
|
|
92
|
+
category,
|
|
93
|
+
count(*) AS item_count,
|
|
94
|
+
sum(price) AS gross_revenue
|
|
95
|
+
FROM read_parquet(?)
|
|
96
|
+
GROUP BY category
|
|
97
|
+
ORDER BY gross_revenue DESC
|
|
98
|
+
`, [parquetPath]);
|
|
99
|
+
|
|
100
|
+
await db.close();
|
|
101
|
+
return rows;
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
### 4. MotherDuck Cloud Hybrid Execution
|
|
108
|
+
|
|
109
|
+
Scale seamlessly from a single laptop to collaborative cloud storage without modifying SQL queries:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
import duckdb
|
|
113
|
+
|
|
114
|
+
# Connect to MotherDuck (cloud database)
|
|
115
|
+
con = duckdb.connect("md:production_analytics")
|
|
116
|
+
|
|
117
|
+
# Join local disk Parquet files directly with MotherDuck cloud tables
|
|
118
|
+
con.execute("""
|
|
119
|
+
SELECT
|
|
120
|
+
cloud_users.organization_id,
|
|
121
|
+
count(local_events.event_id) AS event_volume
|
|
122
|
+
FROM read_parquet('./local_cache/*.parquet') AS local_events
|
|
123
|
+
JOIN cloud_users ON local_events.user_id = cloud_users.id
|
|
124
|
+
GROUP BY cloud_users.organization_id
|
|
125
|
+
""")
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 🛠️ Performance Checklist
|
|
131
|
+
|
|
132
|
+
- **Use Parquet Over CSV**: Parquet is 10x-50x faster due to columnar compression, statistics dictionaries, and column skipping.
|
|
133
|
+
- **Configure Memory Limit**: Always set `SET memory_limit = 'XGB';` to ensure DuckDB uses external sorting/joining when data exceeds RAM instead of crashing the process.
|
|
134
|
+
- **Avoid Row-by-Row Inserts**: Use `Appender` or `COPY ... FROM ...` in bulk batches of 50,000+ rows.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fastapi-production
|
|
3
|
+
description: >-
|
|
4
|
+
Architects, builds, and reviews production-grade async FastAPI backends with Pydantic v2, lifespan context management, JWT auth, dependency injection, and health probes.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# FastAPI Production Architect
|
|
8
|
+
|
|
9
|
+
This skill guides building high-performance, asynchronous REST APIs with FastAPI, adhering to production standards, strict type safety with Pydantic v2, clean dependency injection, and cloud-native observability.
|
|
10
|
+
|
|
11
|
+
## 🏗️ Production Directory Layout
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
app/
|
|
15
|
+
├── api/
|
|
16
|
+
│ ├── deps.py # Shared dependencies (DB sessions, current user, rate limiters)
|
|
17
|
+
│ └── v1/
|
|
18
|
+
│ ├── router.py # Root v1 router aggregating feature endpoints
|
|
19
|
+
│ └── endpoints/
|
|
20
|
+
│ ├── auth.py # Authentication & token renewal
|
|
21
|
+
│ └── users.py # User management endpoints
|
|
22
|
+
├── core/
|
|
23
|
+
│ ├── config.py # Pydantic BaseSettings environment validation
|
|
24
|
+
│ ├── database.py # Async SQLAlchemy engine & session factory
|
|
25
|
+
│ └── security.py # JWT encoding/decoding & Argon2/bcrypt hashing
|
|
26
|
+
├── models/ # SQLAlchemy ORM database models
|
|
27
|
+
├── schemas/ # Pydantic v2 request/response schemas
|
|
28
|
+
├── services/ # Pure domain business logic
|
|
29
|
+
└── main.py # FastAPI application initialization & lifespan
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## ⚡ Core Patterns
|
|
35
|
+
|
|
36
|
+
### 1. Lifespan State Management
|
|
37
|
+
|
|
38
|
+
Avoid deprecated `@app.on_event("startup")` and `@app.on_event("shutdown")`. Use modern async context lifespans:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from contextlib import asynccontextmanager
|
|
42
|
+
from fastapi import FastAPI
|
|
43
|
+
from app.core.database import engine
|
|
44
|
+
from app.core.redis import init_redis_pool, close_redis_pool
|
|
45
|
+
|
|
46
|
+
@asynccontextmanager
|
|
47
|
+
async def lifespan(app: FastAPI):
|
|
48
|
+
# Startup: Initialize connection pools, caches, and telemetry
|
|
49
|
+
app.state.redis = await init_redis_pool()
|
|
50
|
+
try:
|
|
51
|
+
yield
|
|
52
|
+
finally:
|
|
53
|
+
# Shutdown: Gracefully drain connections
|
|
54
|
+
await close_redis_pool(app.state.redis)
|
|
55
|
+
await engine.dispose()
|
|
56
|
+
|
|
57
|
+
app = FastAPI(title="Production Service", lifespan=lifespan)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 2. Pydantic v2 Request & Response Schemas
|
|
61
|
+
|
|
62
|
+
Enforce strict validation, immutable attributes where appropriate, and forbid undeclared payloads:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from pydantic import BaseModel, ConfigDict, EmailStr, Field
|
|
66
|
+
|
|
67
|
+
class UserBase(BaseModel):
|
|
68
|
+
model_config = ConfigDict(
|
|
69
|
+
from_attributes=True,
|
|
70
|
+
extra="forbid",
|
|
71
|
+
str_strip_whitespace=True,
|
|
72
|
+
)
|
|
73
|
+
email: EmailStr
|
|
74
|
+
is_active: bool = True
|
|
75
|
+
|
|
76
|
+
class UserCreate(UserBase):
|
|
77
|
+
password: str = Field(min_length=8, max_length=128)
|
|
78
|
+
|
|
79
|
+
class UserResponse(UserBase):
|
|
80
|
+
id: int
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 3. Dependency Injection & Database Sessions
|
|
84
|
+
|
|
85
|
+
Inject asynchronous SQLAlchemy sessions using an `async_sessionmaker` generator yielding into FastAPI's `Depends`:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from collections.abc import AsyncGenerator
|
|
89
|
+
from fastapi import Depends
|
|
90
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
91
|
+
from app.core.database import async_session_factory
|
|
92
|
+
|
|
93
|
+
async def get_db_session() -> AsyncGenerator[AsyncSession, None]:
|
|
94
|
+
async with async_session_factory() as session:
|
|
95
|
+
try:
|
|
96
|
+
yield session
|
|
97
|
+
await session.commit()
|
|
98
|
+
except Exception:
|
|
99
|
+
await session.rollback()
|
|
100
|
+
raise
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 4. JWT Authentication & Permission Guards
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from typing import Annotated
|
|
107
|
+
from fastapi import Depends, HTTPException, status
|
|
108
|
+
from fastapi.security import OAuth2PasswordBearer
|
|
109
|
+
from app.schemas.user import UserResponse
|
|
110
|
+
from app.services.auth import decode_jwt_token
|
|
111
|
+
|
|
112
|
+
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
|
|
113
|
+
|
|
114
|
+
async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]) -> UserResponse:
|
|
115
|
+
user = await decode_jwt_token(token)
|
|
116
|
+
if not user or not user.is_active:
|
|
117
|
+
raise HTTPException(
|
|
118
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
119
|
+
detail="Invalid authentication credentials",
|
|
120
|
+
headers={"WWW-Authenticate": "Bearer"},
|
|
121
|
+
)
|
|
122
|
+
return user
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 5. Standardized Problem Details Error Envelope (RFC 7807)
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from fastapi import Request
|
|
129
|
+
from fastapi.responses import JSONResponse
|
|
130
|
+
|
|
131
|
+
async def global_exception_handler(request: Request, exc: Exception) -> JSONResponse:
|
|
132
|
+
return JSONResponse(
|
|
133
|
+
status_code=500,
|
|
134
|
+
content={
|
|
135
|
+
"type": "https://errors.example.com/internal-server-error",
|
|
136
|
+
"title": "Internal Server Error",
|
|
137
|
+
"status": 500,
|
|
138
|
+
"detail": "An unexpected error occurred. Please contact engineering support.",
|
|
139
|
+
"instance": str(request.url.path),
|
|
140
|
+
},
|
|
141
|
+
)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 6. Kubernetes Liveness & Readiness Probes
|
|
145
|
+
|
|
146
|
+
Expose separate endpoints for orchestrator checks:
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
@app.get("/healthz/liveness", tags=["Health"])
|
|
150
|
+
async def liveness_check():
|
|
151
|
+
return {"status": "ok"}
|
|
152
|
+
|
|
153
|
+
@app.get("/healthz/readiness", tags=["Health"])
|
|
154
|
+
async def readiness_check(db: AsyncSession = Depends(get_db_session)):
|
|
155
|
+
await db.execute(text("SELECT 1"))
|
|
156
|
+
return {"status": "ready"}
|
|
157
|
+
```
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: grpc-connect-rpc
|
|
3
|
+
description: >-
|
|
4
|
+
Architects and implements high-performance, browser-compatible gRPC and Protocol Buffer services using Connect-RPC (Connect-ES & Connect-Go), HTTP/2 & HTTP/3 streaming, and type-safe schema generation.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Connect-RPC & Modern Protocol Buffers
|
|
8
|
+
|
|
9
|
+
This skill guides building fast, ergonomic, and 100% browser-compatible RPC services using Connect-RPC (by Buf). Connect implements the gRPC, gRPC-Web, and Connect protocols natively over HTTP/1.1, HTTP/2, and HTTP/3 without requiring Envoy proxy sidecars.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## ⚡ Core Patterns
|
|
14
|
+
|
|
15
|
+
### 1. Protobuf Service Definition (`buf.build` Standard)
|
|
16
|
+
|
|
17
|
+
Define service contracts and strongly-typed data structures:
|
|
18
|
+
|
|
19
|
+
```protobuf
|
|
20
|
+
// proto/commerce/v1/order.proto
|
|
21
|
+
syntax = "proto3";
|
|
22
|
+
|
|
23
|
+
package commerce.v1;
|
|
24
|
+
|
|
25
|
+
option go_package = "github.com/company/commerce/gen/commerce/v1;commercev1";
|
|
26
|
+
|
|
27
|
+
service OrderService {
|
|
28
|
+
rpc CreateOrder(CreateOrderRequest) returns (CreateOrderResponse);
|
|
29
|
+
rpc StreamOrderUpdates(StreamOrderUpdatesRequest) returns (stream StreamOrderUpdatesResponse);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
message CreateOrderRequest {
|
|
33
|
+
string customer_id = 1;
|
|
34
|
+
repeated OrderItem items = 2;
|
|
35
|
+
double total_usd = 3;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
message OrderItem {
|
|
39
|
+
string sku = 1;
|
|
40
|
+
int32 quantity = 2;
|
|
41
|
+
double price_usd = 3;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
message CreateOrderResponse {
|
|
45
|
+
string order_id = 1;
|
|
46
|
+
string status = 2;
|
|
47
|
+
int64 created_at_unix = 3;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
message StreamOrderUpdatesRequest {
|
|
51
|
+
string order_id = 1;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
message StreamOrderUpdatesResponse {
|
|
55
|
+
string order_id = 1;
|
|
56
|
+
string current_status = 2;
|
|
57
|
+
string message = 3;
|
|
58
|
+
int64 timestamp = 4;
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Compile with `buf generate`:
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
# buf.gen.yaml
|
|
66
|
+
version: v2
|
|
67
|
+
plugins:
|
|
68
|
+
- local: protoc-gen-es
|
|
69
|
+
out: gen/ts
|
|
70
|
+
opt: target=ts
|
|
71
|
+
- local: protoc-gen-connect-es
|
|
72
|
+
out: gen/ts
|
|
73
|
+
opt: target=ts
|
|
74
|
+
- local: protoc-gen-go
|
|
75
|
+
out: gen/go
|
|
76
|
+
opt: paths=source_relative
|
|
77
|
+
- local: protoc-gen-connect-go
|
|
78
|
+
out: gen/go
|
|
79
|
+
opt: paths=source_relative
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
### 2. Node.js / TypeScript Server Implementation (Connect-ES)
|
|
85
|
+
|
|
86
|
+
Implement the typed service handler with zero boilerplate:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { ConnectRouter } from '@connectrpc/connect';
|
|
90
|
+
import { OrderService } from './gen/ts/commerce/v1/order_connect';
|
|
91
|
+
import { fastify } from 'fastify';
|
|
92
|
+
import { fastifyConnectPlugin } from '@connectrpc/connect-fastify';
|
|
93
|
+
|
|
94
|
+
function routes(router: ConnectRouter) {
|
|
95
|
+
router.service(OrderService, {
|
|
96
|
+
async createOrder(req) {
|
|
97
|
+
if (!req.customerId || req.items.length === 0) {
|
|
98
|
+
throw new ConnectError('Order must contain a customerId and items', Code.InvalidArgument);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const orderId = `ord_${crypto.randomUUID().slice(0, 8)}`;
|
|
102
|
+
return {
|
|
103
|
+
orderId,
|
|
104
|
+
status: 'PENDING_PAYMENT',
|
|
105
|
+
createdAtUnix: BigInt(Date.now()),
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
async *streamOrderUpdates(req) {
|
|
110
|
+
const statuses = ['PAYMENT_CONFIRMED', 'WAREHOUSE_PICKED', 'IN_TRANSIT', 'DELIVERED'];
|
|
111
|
+
for (const status of statuses) {
|
|
112
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
113
|
+
yield {
|
|
114
|
+
orderId: req.orderId,
|
|
115
|
+
currentStatus: status,
|
|
116
|
+
message: `Package status updated to ${status}`,
|
|
117
|
+
timestamp: BigInt(Date.now()),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const server = fastify({ http2: true });
|
|
125
|
+
await server.register(fastifyConnectPlugin, { routes });
|
|
126
|
+
await server.listen({ host: '0.0.0.0', port: 8080 });
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
### 3. Native Browser Client (No Envoy Proxy Needed)
|
|
132
|
+
|
|
133
|
+
Invoke typed RPCs directly from modern browsers or Next.js applications:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { createClient } from '@connectrpc/connect';
|
|
137
|
+
import { createConnectTransport } from '@connectrpc/connect-web';
|
|
138
|
+
import { OrderService } from './gen/ts/commerce/v1/order_connect';
|
|
139
|
+
|
|
140
|
+
// Transport supports pure HTTP POST requests with JSON or binary Protobuf envelopes
|
|
141
|
+
const transport = createConnectTransport({
|
|
142
|
+
baseUrl: 'https://api.example.com',
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const client = createClient(OrderService, transport);
|
|
146
|
+
|
|
147
|
+
// 1. Unary RPC Call
|
|
148
|
+
const response = await client.createOrder({
|
|
149
|
+
customerId: 'cust_98234',
|
|
150
|
+
items: [{ sku: 'CLOUD-GPU-A100', quantity: 2, priceUsd: 1450.0 }],
|
|
151
|
+
totalUsd: 2900.0,
|
|
152
|
+
});
|
|
153
|
+
console.log('Created order:', response.orderId);
|
|
154
|
+
|
|
155
|
+
// 2. Server Streaming RPC Call
|
|
156
|
+
for await (const update of client.streamOrderUpdates({ orderId: response.orderId })) {
|
|
157
|
+
console.log(`Live Status [${update.currentStatus}]: ${update.message}`);
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 🎯 Verification & Diagnostics
|
|
164
|
+
|
|
165
|
+
1. **Test Service with cURL (Standard HTTP POST)**:
|
|
166
|
+
```bash
|
|
167
|
+
curl \
|
|
168
|
+
--header "Content-Type: application/json" \
|
|
169
|
+
--data '{"customerId": "cust_123", "items": [{"sku": "PROD-1", "quantity": 1, "priceUsd": 99.0}], "totalUsd": 99.0}' \
|
|
170
|
+
https://api.example.com/commerce.v1.OrderService/CreateOrder
|
|
171
|
+
```
|
|
172
|
+
2. **Inspect Buf Lint & Breaking Change Rules**:
|
|
173
|
+
```bash
|
|
174
|
+
buf lint
|
|
175
|
+
buf breaking --against ".git#branch=main"
|
|
176
|
+
```
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: langgraph-orchestrator
|
|
3
|
+
description: >-
|
|
4
|
+
Designs and implements stateful multi-agent systems, cyclic graphs, persistent checkpoints, human-in-the-loop pauses, and streaming orchestration using LangGraph (Python/TypeScript).
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# LangGraph Multi-Agent Orchestration & Stateful Graphs
|
|
8
|
+
|
|
9
|
+
This skill guides the design, construction, and deployment of complex multi-agent architectures using LangGraph. It provides deterministic patterns for cyclic routing, persistent graph checkpointing, and human-in-the-loop (HITL) approval gates.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## ⚡ Core Concepts
|
|
14
|
+
|
|
15
|
+
1. **State Graph (`StateGraph`)**: Typed dictionary or Pydantic state passed through graph nodes.
|
|
16
|
+
2. **Nodes**: Discrete execution functions that receive current state and return state updates.
|
|
17
|
+
3. **Edges & Conditional Edges**: Transition rules between nodes (deterministic or LLM-routed).
|
|
18
|
+
4. **Checkpointers (`BaseCheckpointSaver`)**: Persists graph state across turns and enables time-travel debugging.
|
|
19
|
+
5. **Human-in-the-Loop (`interrupt_before`)**: Pauses execution graph at critical checkpoints for human intervention.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 🏗️ Production Implementation (Python)
|
|
24
|
+
|
|
25
|
+
### 1. State Definition & Reducers (`state.py`)
|
|
26
|
+
|
|
27
|
+
Define immutable state schemas with explicit reducer operators:
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from typing import Annotated, Sequence, TypedDict
|
|
31
|
+
from langchain_core.messages import BaseMessage
|
|
32
|
+
from langgraph.graph.message import add_messages
|
|
33
|
+
|
|
34
|
+
class AgentState(TypedDict):
|
|
35
|
+
# add_messages reducer appends new messages rather than overwriting
|
|
36
|
+
messages: Annotated[Sequence[BaseMessage], add_messages]
|
|
37
|
+
sender: str
|
|
38
|
+
iteration_count: int
|
|
39
|
+
is_approved: bool
|
|
40
|
+
context_data: dict
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
### 2. Multi-Agent Nodes & Graph Assembly (`graph.py`)
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from langgraph.graph import StateGraph, END, START
|
|
49
|
+
from langgraph.checkpoint.memory import MemorySaver
|
|
50
|
+
from langchain_core.messages import AIMessage, HumanMessage
|
|
51
|
+
|
|
52
|
+
def researcher_node(state: AgentState) -> dict:
|
|
53
|
+
"""Researches user inquiry and extracts factual grounding."""
|
|
54
|
+
# LLM invocation logic here
|
|
55
|
+
result = "Research findings: latency reduced by 40% via caching."
|
|
56
|
+
return {
|
|
57
|
+
"messages": [AIMessage(content=result, name="researcher")],
|
|
58
|
+
"sender": "researcher",
|
|
59
|
+
"iteration_count": state.get("iteration_count", 0) + 1,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
def reviewer_node(state: AgentState) -> dict:
|
|
63
|
+
"""Validates research quality and enforces compliance."""
|
|
64
|
+
last_msg = state["messages"][-1].content
|
|
65
|
+
approved = "latency" in last_msg.lower()
|
|
66
|
+
return {
|
|
67
|
+
"messages": [AIMessage(content="Review complete.", name="reviewer")],
|
|
68
|
+
"sender": "reviewer",
|
|
69
|
+
"is_approved": approved,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
def human_approval_node(state: AgentState) -> dict:
|
|
73
|
+
"""Node executed after human approval gate."""
|
|
74
|
+
return {"messages": [AIMessage(content="Action executed after sign-off.", name="human_gate")]}
|
|
75
|
+
|
|
76
|
+
def router_condition(state: AgentState) -> str:
|
|
77
|
+
"""Evaluate whether to loop or terminate."""
|
|
78
|
+
if state.get("is_approved", False):
|
|
79
|
+
return "human_approval"
|
|
80
|
+
if state.get("iteration_count", 0) >= 3:
|
|
81
|
+
return "abort"
|
|
82
|
+
return "researcher"
|
|
83
|
+
|
|
84
|
+
# Build State Graph
|
|
85
|
+
workflow = StateGraph(AgentState)
|
|
86
|
+
|
|
87
|
+
# Add Nodes
|
|
88
|
+
workflow.add_node("researcher", researcher_node)
|
|
89
|
+
workflow.add_node("reviewer", reviewer_node)
|
|
90
|
+
workflow.add_node("human_approval", human_approval_node)
|
|
91
|
+
|
|
92
|
+
# Add Edges
|
|
93
|
+
workflow.add_edge(START, "researcher")
|
|
94
|
+
workflow.add_edge("researcher", "reviewer")
|
|
95
|
+
workflow.add_conditional_edges(
|
|
96
|
+
"reviewer",
|
|
97
|
+
router_condition,
|
|
98
|
+
{
|
|
99
|
+
"human_approval": "human_approval",
|
|
100
|
+
"researcher": "researcher",
|
|
101
|
+
"abort": END,
|
|
102
|
+
}
|
|
103
|
+
)
|
|
104
|
+
workflow.add_edge("human_approval", END)
|
|
105
|
+
|
|
106
|
+
# Compile with Persistent Checkpointer and Human-in-the-Loop Interruption
|
|
107
|
+
checkpointer = MemorySaver()
|
|
108
|
+
app = workflow.compile(
|
|
109
|
+
checkpointer=checkpointer,
|
|
110
|
+
interrupt_before=["human_approval"]
|
|
111
|
+
)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### 3. Execution & Human-in-the-Loop Resumption
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
thread_config = {"configurable": {"thread_id": "session-prod-1024"}}
|
|
120
|
+
|
|
121
|
+
# Run until human interrupt
|
|
122
|
+
inputs = {"messages": [HumanMessage(content="Optimize database latency.")], "iteration_count": 0}
|
|
123
|
+
for event in app.stream(inputs, config=thread_config):
|
|
124
|
+
print(f"Step: {event}")
|
|
125
|
+
|
|
126
|
+
# Inspect current snapshot before approval
|
|
127
|
+
snapshot = app.get_state(thread_config)
|
|
128
|
+
print(f"Next Node Pending Approval: {snapshot.next}")
|
|
129
|
+
|
|
130
|
+
# Resume graph after human confirmation
|
|
131
|
+
for event in app.stream(None, config=thread_config):
|
|
132
|
+
print(f"Post-approval Step: {event}")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 🛡️ Best Practices & Anti-Patterns
|
|
138
|
+
|
|
139
|
+
| Category | ❌ Anti-Pattern | ✅ Production Best Practice |
|
|
140
|
+
| :--- | :--- | :--- |
|
|
141
|
+
| **State Mutation** | Modifying state objects in-place | Return clean partial state dictionaries with reducer keys |
|
|
142
|
+
| **Cycles** | Unbounded recursive loops | Enforce explicit `iteration_count` or recursion limit (`recursion_limit=25`) |
|
|
143
|
+
| **Checkpoints** | Storing giant binary blobs in state | Keep state lean; persist media in object stores (GCS/S3) and store URIs |
|
|
144
|
+
| **HITL** | Hardcoded polling loops | Use native `interrupt_before` / `interrupt_after` with thread configurations |
|