Autonomous agent that requests designs from Google Stitch via its API and integrates them into the active project. The full flow is:
text
OAuth Token → Design Prompt → Stitch API → Generated Code → Project Integration
ResourceWhere to get itGoogle OAuth 2.0 token with cloud-platform scopeStep 2 belowActive project (React / NestJS / any stack)Must already be in the workspaceSTITCH_TOKEN environment variable.env file or agent secret
bash
# 1. Redirect the user to the authorization URL
GET https://accounts.google.com/o/oauth2/v2/auth
?client_id=<CLIENT_ID>
&redirect_uri=<REDIRECT_URI>
&response_type=code
&scope=https://www.googleapis.com/auth/cloud-platform
&access_type=offline
# 2. Exchange the authorization code for tokens
POST https://oauth2.googleapis.com/token
grant_type=authorization_code
&code=<CODE>
&client_id=<CLIENT_ID>
&client_secret=<CLIENT_SECRET>
&redirect_uri=<REDIRECT_URI>
# Response:
# { "access_token": "ya29.xxx", "refresh_token": "1//xxx", "expires_in": 3599 }
bash
# Generate a signed JWT with the service account key and exchange it:
POST https://oauth2.googleapis.com/token
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&assertion=<SIGNED_JWT>
The agent must always read the token from the
STITCH_TOKENenvironment variable. Never hardcode tokens in source code.
text
POST https://stitch.googleapis.com/v1/designs:generate
Authorization: Bearer {STITCH_TOKEN}
Content-Type: application/json
json
{
"prompt": "<natural language description of the desired design>",
"output_format": "react_component", // "html" | "react_component" | "vue_component"
"theme": {
"primary_color": "#3B82F6",
"font_family": "Inter"
},
"context": {
"framework": "react",
"styling": "tailwind" // "css_modules" | "tailwind" | "styled_components"
}
}
text
"Create a financial summary card component with:
- Total balance prominently displayed at the top
- Small bar chart showing the last 7 days
- Two action buttons: Income and Expense
- Minimalist style with a soft shadow
- Dark mode compatible"
json
{
"design_id": "dsgn_abc123",
"component_name": "FinancialSummaryCard",
"code": "import React from 'react';\n\nexport const FinancialSummaryCard = ...",
"assets": [],
"metadata": {
"tokens_used": 840,
"framework": "react"
}
}
typescript
// The agent must:
// 1. Extract `response.code` from the Stitch response
// 2. Determine the correct path based on the project structure
const componentName = response.component_name; // e.g. "FinancialSummaryCard"
const targetPath = `src/components/${componentName}.tsx`;
// 3. Write the file
fs.writeFileSync(targetPath, response.code, 'utf-8');
The agent should scan the project to find the most logical integration point:
bash
# Find files that are likely to use the new component
grep -r "Dashboard\|Overview\|Home\|Layout" src/pages --include="*.tsx" -l
typescript
// Add to the target file:
import { FinancialSummaryCard } from '../components/FinancialSummaryCard';
// And in the JSX:
<FinancialSummaryCard />
bash
npx tsc --noEmit # Check TypeScript types
npm run lint -- --fix # Auto-fix linting issues
typescript
async function stitchDesignFlow(userPrompt: string) {
// Step 1: Read token
const token = process.env.STITCH_TOKEN;
if (!token) throw new Error('STITCH_TOKEN is not configured');
// Step 2: Request design from Stitch
const stitchResponse = await fetch(
'https://stitch.googleapis.com/v1/designs:generate',
{
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
prompt: userPrompt,
output_format: 'react_component',
context: { framework: 'react', styling: 'tailwind' },
}),
}
);
const design = await stitchResponse.json();
// Step 3: Save the component
const filePath = `src/components/${design.component_name}.tsx`;
fs.writeFileSync(filePath, design.code);
// Step 4: Find the integration point
const integrationTarget = await detectIntegrationPoint(design.component_name);
// Step 5: Inject import and JSX
await injectComponent(integrationTarget, design.component_name);
// Step 6: Verify build
execSync('npx tsc --noEmit');
return { filePath, integrationTarget };
}
ErrorLikely causeAgent action401 UnauthorizedToken expired or invalidAsk the user for a new token or refresh automatically400 Bad RequestPrompt too vague or invalid payloadRefine the prompt and retry429 Too Many RequestsRate limit reachedWait 60s and retryTypeScript errorsGenerated component has incorrect typesFix types manually or request regenerationImport conflictsComponent name already exists in the projectRename with a _v2 suffix
yaml
# openclaw.config.yml (relevant section)
agents:
stitch-designer:
skill: stitch-design-agent
env:
STITCH_TOKEN: ${secrets.GOOGLE_STITCH_TOKEN}
tools:
- file_write
- file_read
- bash
- web_fetch
triggers:
- "design a component"
- "ask stitch for the design"
- "integrate UI from stitch"
- "generate the view for"
- "create a screen for"
refresh_token to
renew it automatically before retrying.recharts, framer-motion) and run npm install <pkg> before integrating.src/modules/<domain>/components/, not at the src/components/ root.