@@ -8,6 +8,10 @@ import { requireRole } from '@/lib/auth';
88import { mutationLimiter } from '@/lib/rate-limit' ;
99import { logger } from '@/lib/logger' ;
1010import { validateBody , createAgentSchema } from '@/lib/validation' ;
11+ import { runOpenClaw } from '@/lib/command' ;
12+ import { config as appConfig } from '@/lib/config' ;
13+ import { resolveWithin } from '@/lib/paths' ;
14+ import path from 'node:path' ;
1115
1216/**
1317 * GET /api/agents - List all agents with optional filtering
@@ -123,16 +127,24 @@ export async function POST(request: NextRequest) {
123127
124128 const {
125129 name,
130+ openclaw_id,
126131 role,
127132 session_key,
128133 soul_content,
129134 status = 'offline' ,
130135 config = { } ,
131136 template,
132137 gateway_config,
133- write_to_gateway
138+ write_to_gateway,
139+ provision_openclaw_workspace,
140+ openclaw_workspace_path
134141 } = body ;
135142
143+ const openclawId = ( openclaw_id || name || 'agent' )
144+ . toLowerCase ( )
145+ . replace ( / [ ^ a - z 0 - 9 ] + / g, '-' )
146+ . replace ( / ^ - | - $ / g, '' ) ;
147+
136148 // Resolve template if specified
137149 let finalRole = role ;
138150 let finalConfig : Record < string , any > = { ...config } ;
@@ -158,6 +170,32 @@ export async function POST(request: NextRequest) {
158170 if ( existingAgent ) {
159171 return NextResponse . json ( { error : 'Agent name already exists' } , { status : 409 } ) ;
160172 }
173+
174+ if ( provision_openclaw_workspace ) {
175+ if ( ! appConfig . openclawStateDir ) {
176+ return NextResponse . json (
177+ { error : 'OPENCLAW_STATE_DIR is not configured; cannot provision OpenClaw workspace' } ,
178+ { status : 500 }
179+ ) ;
180+ }
181+
182+ const workspacePath = openclaw_workspace_path
183+ ? path . resolve ( openclaw_workspace_path )
184+ : resolveWithin ( appConfig . openclawStateDir , path . join ( 'workspaces' , openclawId ) ) ;
185+
186+ try {
187+ await runOpenClaw (
188+ [ 'agents' , 'add' , openclawId , '--name' , name , '--workspace' , workspacePath , '--non-interactive' ] ,
189+ { timeoutMs : 20000 }
190+ ) ;
191+ } catch ( provisionError : any ) {
192+ logger . error ( { err : provisionError , openclawId, workspacePath } , 'OpenClaw workspace provisioning failed' ) ;
193+ return NextResponse . json (
194+ { error : provisionError ?. message || 'Failed to provision OpenClaw agent workspace' } ,
195+ { status : 502 }
196+ ) ;
197+ }
198+ }
161199
162200 const now = Math . floor ( Date . now ( ) / 1000 ) ;
163201
@@ -215,7 +253,6 @@ export async function POST(request: NextRequest) {
215253 // Write to gateway config if requested
216254 if ( write_to_gateway && finalConfig ) {
217255 try {
218- const openclawId = ( name || 'agent' ) . toLowerCase ( ) . replace ( / \s + / g, '-' ) ;
219256 await writeAgentToConfig ( {
220257 id : openclawId ,
221258 name,
0 commit comments