Generate photos where your OpenClaw character looks the same every time — selfies, group shots, portraits, stylized scenes, and more — all through tuqu.ai's image generation API. The skill handles character identity preservation, prompt enhancement, preset application, balance management, and billing.
bash
clawhub install openclaw-selfie
Or with the native OpenClaw command:
bash
openclaw skills install openclaw-selfie
python3 in PATH).--service-key.After installation, verify the skill is working:
bash
# Check that the helper script runs
python3 scripts/tuqu_request.py GET /api/catalog --query type=all
# Check available models and pricing
python3 scripts/tuqu_request.py GET /api/pricing-config
If both commands return JSON, the skill is ready. Authenticated calls (generation, balance, etc.)
also require --service-key <your-role-service-key>.
Only set these when you need to point at a non-default host:
TUQU_BASE_URL — defaults to https://photo.tuqu.aiTUQU_BILLING_BASE_URL — defaults to https://billing.tuqu.ai/dream-weaverAll API calls go through scripts/tuqu_request.py. The helper auto-selects the correct host and
auth mode for each endpoint, keeps credentials explicit via --service-key, and prints formatted
JSON for direct inspection.
Detailed API semantics are in TUQU_API.md. Exact request/response fields are in references/endpoints.md and task sequences in references/workflows.md.
Authenticated calls must pass --service-key <role-service-key> explicitly on every request. Do not
rely on a shared credential environment variable — different OpenClaw roles can carry different keys.
List or query data:
bash
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:
bash
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:
bash
python3 scripts/tuqu_request.py POST /api/v2/generate-image \
--service-key <role-service-key> \
--body-file payloads/generate-image.json
Override helper defaults only with a documented reason:
bash
python3 scripts/tuqu_request.py POST /api/custom-path \
--base-url https://photo.tuqu.ai \
--auth-mode user-key \
--service-key <role-service-key> \
--json '{"prompt":"example"}'
Before picking an endpoint, classify the user request into one of these buckets:
自拍, 照片, 写真, 发张图, or similar wording that implies the current role should be in frameIf the request is ambiguous, decide whether the current role needs to appear in the final image.
自拍 as current-role-on-camera by default.自拍 means the current role appears in the image. It does not mean a phone must be visible.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.
When the current role must appear in the frame, enforce this order:
/api/characters./api/billing/balance./api/v2/generate-for-character.Helper sequence:
bash
python3 scripts/tuqu_request.py GET /api/characters --service-key <role-service-key>
python3 scripts/tuqu_request.py POST /api/characters \
--service-key <role-service-key> \
--body-file payloads/create-character.json
python3 scripts/tuqu_request.py POST /api/billing/balance --service-key <role-service-key>
python3 scripts/tuqu_request.py POST /api/v2/generate-for-character \
--service-key <role-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.
自拍 or 发张图, assume the goal is a natural current-role portrait rather
than a literal handheld-phone shot.bash
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.
bash
python3 scripts/tuqu_request.py POST /api/enhance-prompt \
--json '{"category":"portrait","prompt":"soft editorial portrait with window light"}'
bash
python3 scripts/tuqu_request.py POST /api/v2/generate-image \
--service-key <role-service-key> \
--body-file payloads/generate-image.json
Example payloads/generate-image.json:
json
{
"prompt": "cinematic portrait in warm sunset light",
"referenceImageUrls": ["https://example.com/reference.jpg"],
"resolution": "2K",
"ratio": "Original",
"modelId": "seedream45"
}
bash
python3 scripts/tuqu_request.py GET /api/catalog --query type=all
python3 scripts/tuqu_request.py POST /api/v2/apply-preset \
--service-key <role-service-key> \
--body-file payloads/apply-preset.json
bash
python3 scripts/tuqu_request.py GET /api/characters --service-key <role-service-key>
python3 scripts/tuqu_request.py POST /api/characters \
--service-key <role-service-key> \
--body-file payloads/create-character.json
python3 scripts/tuqu_request.py PUT /api/characters/<character-id> \
--service-key <role-service-key> \
--body-file payloads/update-character.json
python3 scripts/tuqu_request.py DELETE /api/characters/<character-id> \
--service-key <role-service-key>
bash
python3 scripts/tuqu_request.py GET /api/characters --service-key <role-service-key>
python3 scripts/tuqu_request.py POST /api/billing/balance --service-key <role-service-key>
python3 scripts/tuqu_request.py POST /api/v2/generate-for-character \
--service-key <role-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.
bash
python3 scripts/tuqu_request.py GET /api/history --service-key <role-service-key>
python3 scripts/tuqu_request.py POST /api/history \
--service-key <role-service-key> \
--body-file payloads/history-item.json
python3 scripts/tuqu_request.py DELETE /api/history/<history-id> --service-key <role-service-key>
python3 scripts/tuqu_request.py POST /api/billing/balance --service-key <role-service-key>
bash
python3 scripts/tuqu_request.py GET /api/v1/recharge/plans --service-key <role-service-key>
python3 scripts/tuqu_request.py POST /api/v1/recharge/wechat \
--service-key <role-service-key> \
--json '{"planId":"698b7fead4c733c85f2a9c74"}'
python3 scripts/tuqu_request.py POST /api/v1/recharge/stripe \
--service-key <role-service-key> \
--json '{"planId":"698b7fead4c733c85f2a9c74","successUrl":"https://your-app.com/payment/success","cancelUrl":"https://your-app.com/payment/cancel"}'
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
visible unless explicitly requested.