OpenClaw Role Builder
by @zhouyi531
Build and manage OpenClaw roles — create a full AI character role from any public figure or fictional character, then generate identity-consistent selfies an...
clawhub install openclaw-role-builder📖 About This Skill
name: tuqu-photo-api description: >- Generate identity-consistent selfies, group photos, and other SFW images for OpenClaw characters via the tuqu.ai API. Use when creating character portraits, selfies (自拍), photo shoots (写真), group shots (合影), or any image generation request where the character's appearance must stay consistent across images. Covers prompt enhancement, preset discovery, character management, billing, and recharge flows. Also handles 照片, 发张图, 角色出镜, 风景, and edit-only images. metadata: >- {"openclaw":{"emoji":"📸","requires":{"anyBins":["python3"]},"os":["linux","darwin","win32"]}}
Tuqu Photo API
Overview
Use this skill through scripts/tuqu_request.py. For supported paths, the helper picks the correct
host, applies the correct auth mode, keeps credentials explicit via --service-key, and prints
formatted JSON for direct inspection.
Keep API semantics in TUQU_API.md. Keep exact request and response fields in references/endpoints.md and task sequences in references/workflows.md.
How to Obtain a TuQu Service Key
When the user asks how to get a service key, or when a service key is needed but not yet provided, guide the user with these exact steps:
1. Open --service-key on each tuqu_request.py call (the script does not read credentials from environment variables).
Security note: Do NOT ask the user to paste service keys directly into the chat. Service keys are sensitive credentials. Recommend one of these approaches instead:
--service-key sk-... on eachscripts/tuqu_request.py call. The script only accepts service keys via this CLI flag — it
does NOT read any credential from environment variables.
SK="sk-..."), then pass --service-key "$SK" to each call. The variable lives only in the
current shell session and is never read by the script itself.
Never write, persist, or log service keys to disk. Never embed service keys in JSON files, config files, or script source code.
Always show the reference image below to help the user locate the controls on the dashboard:
Annotations in the image: 1. Create Key — click "+ Create Key" to generate a new service key. 2. Copy — click the copy icon next to an existing key to copy it. 3. Rename — click the pencil icon to rename a key. Consider giving each character its own service key for easier tracking; billing is unified at the account level.
Do not invent alternative paths (e.g. "Settings / API Keys", "OpenClaw UI TuQu settings"). The only correct entry point is the URL above.
Configure Only When Needed
Only set these when overriding defaults:
TUQU_BASE_URL=https://photo.tuqu.aiTUQU_BILLING_BASE_URL=https://billing.tuqu.aiAuthenticated calls must pass --service-key explicitly. The script does not
read credentials from environment variables — --service-key is the only credential input.
Use These Command Patterns
List or query data:
python3 scripts/tuqu_request.py GET /api/catalog --query type=all
python3 scripts/tuqu_request.py GET /api/model-costs
python3 scripts/tuqu_request.py GET /api/pricing-config
Send a small JSON body inline:
python3 scripts/tuqu_request.py POST /api/enhance-prompt \
--json '{"category":"portrait","prompt":"soft editorial portrait with window light"}'
Send a larger payload from disk:
python3 scripts/tuqu_request.py POST /api/v2/generate-image \
--service-key \
--body-file payloads/generate-image.json
Override helper defaults only with a documented reason:
python3 scripts/tuqu_request.py POST /api/custom-path \
--base-url https://photo.tuqu.ai \
--auth-mode user-key \
--service-key \
--json '{"prompt":"example"}'
Run Supported Tasks Through the Helper
Classify the Request First
Before picking an endpoint, classify the user request into one of these buckets:
1. Current-role selfie or portrait request:
自拍, 照片, 写真, 发张图, or similar wording that implies the current role should be in frame
2. Character-on-camera request:
the user explicitly wants the current role or a saved character to appear in the image
3. Freestyle or edit-only request:
landscape, objects, scenery, atmosphere shots, or pure image editing without the current role
If the request is ambiguous, decide whether the current role needs to appear in the final image.
Decide Whether the Current Role Must Appear
自拍 as current-role-on-camera by default.自拍 means the current role appears in the image. It does not mean a phone must be visible.Route by Subject Type
Use identity-preserving routing when the current role must appear:
POST /api/v2/generate-for-characterPOST /api/v2/generate-imageKeep all supported calls on scripts/tuqu_request.py.
Run Character Prechecks Before Identity-Preserving Generation
When the current role must appear in the frame, enforce this order:
1. Check whether the current role already has a Tuqu character.
2. If not, create the character first through /api/characters.
3. Check balance through /api/billing/balance.
4. Only then call /api/v2/generate-for-character.
Helper sequence:
python3 scripts/tuqu_request.py GET /api/characters --service-key
python3 scripts/tuqu_request.py POST /api/characters \
--service-key \
--body-file payloads/create-character.json
python3 scripts/tuqu_request.py POST /api/billing/balance --service-key
python3 scripts/tuqu_request.py POST /api/v2/generate-for-character \
--service-key \
--body-file payloads/generate-for-character.json
Use the create-character step only when the current role does not already have a usable Tuqu character.
Apply Default Selfie Behavior
自拍 or 发张图, assume the goal is a natural current-role portrait ratherDiscover presets, models, and pricing
python3 scripts/tuqu_request.py GET /api/catalog --query type=all
python3 scripts/tuqu_request.py GET /api/model-costs
python3 scripts/tuqu_request.py GET /api/pricing-config
Use /api/pricing-config before accepting a user-supplied model name. Match the requested model
to a real models[].id, then use that modelId in later generation payloads.
Improve a prompt
python3 scripts/tuqu_request.py POST /api/enhance-prompt \
--json '{"category":"portrait","prompt":"soft editorial portrait with window light"}'
Generate from prompt or reference images
python3 scripts/tuqu_request.py POST /api/v2/generate-image \
--service-key \
--body-file payloads/generate-image.json
Example payloads/generate-image.json:
{
"prompt": "cinematic portrait in warm sunset light",
"referenceImageUrls": ["https://example.com/reference.jpg"],
"resolution": "2K",
"ratio": "Original",
"modelId": "seedream45"
}
Apply a preset
python3 scripts/tuqu_request.py GET /api/catalog --query type=all
python3 scripts/tuqu_request.py POST /api/v2/apply-preset \
--service-key \
--body-file payloads/apply-preset.json
Manage characters
python3 scripts/tuqu_request.py GET /api/characters --service-key
python3 scripts/tuqu_request.py POST /api/characters \
--service-key \
--body-file payloads/create-character.json
python3 scripts/tuqu_request.py PUT /api/characters/ \
--service-key \
--body-file payloads/update-character.json
python3 scripts/tuqu_request.py DELETE /api/characters/ \
--service-key
Generate with saved characters
python3 scripts/tuqu_request.py GET /api/characters --service-key
python3 scripts/tuqu_request.py POST /api/billing/balance --service-key
python3 scripts/tuqu_request.py POST /api/v2/generate-for-character \
--service-key \
--body-file payloads/generate-for-character.json
Optionally refine the scene prompt first with /api/enhance-prompt. When the request is a selfie
or other current-role portrait, make sure the character check and balance check happen before the
generation call.
Inspect history and balance
python3 scripts/tuqu_request.py GET /api/history --service-key
python3 scripts/tuqu_request.py POST /api/history \
--service-key \
--body-file payloads/history-item.json
python3 scripts/tuqu_request.py DELETE /api/history/ --service-key
python3 scripts/tuqu_request.py POST /api/billing/balance --service-key
Start a recharge flow
python3 scripts/tuqu_request.py GET /api/v1/recharge/plans --service-key
python3 scripts/tuqu_request.py POST /api/v1/recharge/wechat \
--service-key \
--json '{"planId":"698b7fead4c733c85f2a9c74"}'
python3 scripts/tuqu_request.py POST /api/v1/recharge/stripe \
--service-key \
--json '{"planId":"698b7fead4c733c85f2a9c74","successUrl":"https://your-app.com/payment/success","cancelUrl":"https://your-app.com/payment/cancel"}'
Security Boundaries
--service-key CLI flag. Never write,scripts/tuqu_request.py, which restricts requestsphoto.tuqu.ai and billing.tuqu.ai). Do not use curl, wget, or other
HTTP tools to bypass the helper.
payloads/ are read-only inputs prepared by the agent
in the skill's own directory or in the character workspace under ~/.openclaw/.
_meta.json declares requiredEnvVars: []. No environmentOperating Rules
scripts/tuqu_request.py instead of ad-hoc curl for supported endpoints./api/v2/generate-for-character./api/v2/generate-image.--service-key on every authenticated helper call.--body-file for large JSON payloads, especially generation and preset payloads./api/catalog as the source of truth for presetId, preset type, and preset variables./api/pricing-config to resolve user-supplied model names before setting modelId.自拍 as front-camera composition with the current role visible and the phone not