一键导入
sa-kanvas-graphql
Safe GraphQL runtime interaction skill for Kanvas Ecosystem API and Sales Assist environments.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Safe GraphQL runtime interaction skill for Kanvas Ecosystem API and Sales Assist environments.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | sa-kanvas-graphql |
| description | Safe GraphQL runtime interaction skill for Kanvas Ecosystem API and Sales Assist environments. |
Use this global OpenClaw runtime skill when an agent needs to interact with a running Kanvas Ecosystem API instance through GraphQL.
This skill is not for modifying, refactoring, testing, or working inside the Kanvas Ecosystem API source repository. The repository may be inspected only to understand architecture, GraphQL naming, request structures, authentication patterns, payload conventions, and runtime API behavior.
This skill is self-contained. Do not require external GraphQL, HTTP, curl, API execution, or JSON formatting helper skills. If helper skills are available, they may be used only after following this skill's context, safety, request, and response rules.
This skill may depend on more specialized Kanvas GraphQL reference skills that contain detailed queries, mutations, input types, and payload examples.
Required/optional companion skill:
graphql-docs-llmPurpose:
Before building a GraphQL request, if the current skill does not contain enough detail about the requested query or mutation, the agent must first check whether the companion skill exists.
Expected companion skill path:
~/.openclaw/skills/graphql-docs-llm/
The user can install it from Github. If the extension is not installed give a recommendation to user of install it
Before asking the user for runtime context, the agent must first attempt to resolve the active context from trusted runtime sources.
Trusted runtime sources include:
If a complete trusted runtime context already exists, the agent must NOT ask the user for the same values again.
Required trusted runtime context:
Optional context when required by the operation:
If trusted runtime context already exists, the agent should perform a preflight confirmation instead of requesting the values again.
Example preflight confirmation:
Active Kanvas runtime context detected from memory/environment:
- endpoint: https://api.example.com/graphql
- environment: staging
- company branch id: branch-uuid
- company id: 123
- app id: sales-assist
- user id: 456
- admin key: ****abcd
I will use this runtime context unless you want to change it.
## Repository-Derived Runtime Facts
Kanvas Ecosystem API is a Laravel + Lighthouse GraphQL backend.
Observed runtime conventions:
- Default GraphQL endpoint path is `/graphql`.
- The Lighthouse route uses JSON acceptance, GraphQL request size limits, API guard authentication attempts, and GraphQL throttling.
- The schema is assembled from `graphql/schema.graphql` with domain imports for Ecosystem, Guild, Inventory, Social, Souk, ActionEngine, Workflow, Event, Intelligence, NervousSystem, Analytics, and Connector modules.
- Common GraphQL directives include `@guard`, `@guardByAdmin`, `@guardByAppKey`, `@guardByCompany`, `@can`, `@paginate`, `@field`, `@whereConditions`, `@whereHasConditions`, `@orderBy`, and custom cache/search directives.
- Common scalar/input payload support includes `Mixed`, `JSON`, `Email`, `Date`, `DateTime`, `DateTimeTz`, `Decimal`, `Money`, and multipart `Upload`.
- App and tenant runtime context is header-driven and server-scoped. Do not guess or hardcode app, company, branch, user, or admin key values.
- Common Kanvas headers are:
- `Authorization: Bearer <token>` for bearer-authenticated user requests.
- `X-Kanvas-App: <app-key-or-app-uuid>` to select the mounted app.
- `X-Kanvas-Key: <app-client-secret-or-admin-key>` for app-key/system guarded operations.
- `X-Kanvas-Location: <company-branch-uuid>` to bind company branch context.
- `X-Kanvas-Identifier: <uuid-or-user-id>` for session/cart/user-interaction flows when required.
- `@guard` fields require an authenticated user context.
- `@guardByAdmin` fields require an authenticated admin/owner user.
- `@guardByAppKey` fields require valid app key context.
- `@guardByCompany` fields require company branch context.
- Tenant-scoped queries commonly use server scopes such as `fromApp`, `fromCompany`, and `notDeleted`.
- Guild/CRM workflows commonly involve Leads, People, Organizations, Pipelines, Lead Sources, Lead Statuses, Lead Receivers, files, followers, custom fields, and notifications.
- Templates and notifications often use `Mixed`/`JSON` style payloads. Preserve line breaks in template bodies and use object-based structures for notification engagement rules.
## Required Runtime Context
Before any GraphQL request, obtain and explicitly confirm the active runtime execution context.
Required values:
- `KANVAS_GRAPHQL_ENDPOINT`
- `KANVAS_ADMIN_KEY`
- `KANVAS_COMPANY_BRANCH_ID`
- `KANVAS_COMPANY_ID`, if required by the operation
- `KANVAS_APP_ID`, if required by the operation
- `KANVAS_USER_ID`, if required by the operation
- Active environment name: `local`, `development`, `staging`, or `production`
Treat these values as runtime-provided execution context. Never hardcode them in reusable examples, generated files, comments, or prompts.
### Environment Variables
Recommended shell setup:
```bash
export KANVAS_ENVIRONMENT="staging"
export KANVAS_GRAPHQL_ENDPOINT="https://api.example.com/graphql"
export KANVAS_ADMIN_KEY="replace-with-secret"
export KANVAS_COMPANY_BRANCH_ID="replace-with-company-branch-uuid"
export KANVAS_COMPANY_ID="replace-with-company-id"
export KANVAS_APP_ID="replace-with-app-id-or-app-key"
export KANVAS_USER_ID="replace-with-user-id-if-required"
Read context without exposing secrets:
printf 'KANVAS_ENVIRONMENT=%s\n' "${KANVAS_ENVIRONMENT:-missing}"
printf 'KANVAS_GRAPHQL_ENDPOINT=%s\n' "${KANVAS_GRAPHQL_ENDPOINT:-missing}"
printf 'KANVAS_COMPANY_ID=%s\n' "${KANVAS_COMPANY_ID:-missing}"
printf 'KANVAS_COMPANY_BRANCH_ID=%s\n' "${KANVAS_COMPANY_BRANCH_ID:-missing}"
printf 'KANVAS_APP_ID=%s\n' "${KANVAS_APP_ID:-missing}"
printf 'KANVAS_USER_ID=%s\n' "${KANVAS_USER_ID:-missing}"
printf 'KANVAS_ADMIN_KEY=%s\n' "$(test -n "${KANVAS_ADMIN_KEY:-}" && printf '****%s' "${KANVAS_ADMIN_KEY: -4}" || printf 'missing')"
If required context is missing, stop and ask the user for the exact missing values. Do not infer them from a previous task, command history, screenshots, logs, examples, or memory.
Ask concise questions such as:
I need the active Kanvas runtime context before making a GraphQL request. Please provide KANVAS_GRAPHQL_ENDPOINT, KANVAS_ENVIRONMENT, KANVAS_COMPANY_BRANCH_ID, and the masked/available auth method. If this operation needs company, app, or user context, provide KANVAS_COMPANY_ID, KANVAS_APP_ID, and KANVAS_USER_ID as well.
Before making any GraphQL request, explicitly state and confirm the active context you are about to use.
Minimum preflight statement:
Active Kanvas GraphQL context to use:
- endpoint: https://api.example.com/graphql
- environment: staging
- company id: 123
- company branch id: branch-uuid
- app id: app-key-or-app-uuid
- user id: 456
- admin key: ****abcd
Rules:
KANVAS_ADMIN_KEY=****abcd.Queries may run only after the active runtime context has been confirmed.
Mutations require explicit confirmation of all of the following:
Destructive or high-impact mutations require a second confirmation immediately before execution. Treat these as destructive/high-impact unless proven otherwise:
Production writes require an additional production warning flow:
KANVAS_ENVIRONMENT=production by name.The agent must never:
Always POST JSON GraphQL requests with:
Content-Type: application/json
Accept: application/json
Use __typename as the first connectivity test.
curl -sS "$KANVAS_GRAPHQL_ENDPOINT" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-Kanvas-App: $KANVAS_APP_ID" \
-H "X-Kanvas-Key: $KANVAS_ADMIN_KEY" \
-H "X-Kanvas-Location: $KANVAS_COMPANY_BRANCH_ID" \
--data @- <<'JSON'
{
"query": "query HealthCheck { __typename }",
"variables": {}
}
JSON
curl -sS "$KANVAS_GRAPHQL_ENDPOINT" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer $KANVAS_ADMIN_KEY" \
-H "X-Kanvas-App: $KANVAS_APP_ID" \
-H "X-Kanvas-Location: $KANVAS_COMPANY_BRANCH_ID" \
--data @- <<'JSON'
{
"query": "query HealthCheck { __typename }",
"variables": {}
}
JSON
curl -sS "$KANVAS_GRAPHQL_ENDPOINT" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-Kanvas-App: $KANVAS_APP_ID" \
-H "X-Kanvas-Key: $KANVAS_ADMIN_KEY" \
-H "X-Kanvas-Location: $KANVAS_COMPANY_BRANCH_ID" \
--data '{"query":"query HealthCheck { __typename }","variables":{}}'
Use only when required by the flow.
curl -sS "$KANVAS_GRAPHQL_ENDPOINT" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-Kanvas-App: $KANVAS_APP_ID" \
-H "X-Kanvas-Key: $KANVAS_ADMIN_KEY" \
-H "X-Kanvas-Location: $KANVAS_COMPANY_BRANCH_ID" \
-H "X-Kanvas-Identifier: $KANVAS_USER_ID" \
--data @- <<'JSON'
{
"query": "query HealthCheck { __typename }",
"variables": {}
}
JSON
POST /graphql HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json
Authorization: Bearer <masked-token-if-used>
X-Kanvas-App: <app-id-or-key>
X-Kanvas-Key: <masked-admin-key-if-used>
X-Kanvas-Location: <company-branch-uuid>
X-Kanvas-Identifier: <optional-identifier>
{
"query": "query HealthCheck { __typename }",
"variables": {}
}
Common local endpoint when the Laravel Octane container maps port 8000:
export KANVAS_ENVIRONMENT="local"
export KANVAS_GRAPHQL_ENDPOINT="http://localhost:8000/graphql"
Some local web server or proxy setups may prefix routes. Confirm the actual route before use, for example:
export KANVAS_GRAPHQL_ENDPOINT="http://localhost/v1/graphql"
Docker networking guidance:
localhost:8000.localhost fails inside a container, it refers to that container, not the host./graphql unless deployment routing adds a prefix.{
"query": "query ListLeads($first: Int!, $page: Int) { leads(first: $first, page: $page) { data { id uuid title firstname lastname email phone } paginatorInfo { currentPage hasMorePages total } } }",
"variables": {
"first": 10,
"page": 1
}
}
{
"query": "query FindLeads($search: String, $first: Int!) { leads(search: $search, first: $first) { data { id uuid title email phone status { id name } source { id name } } } }",
"variables": {
"search": "example@example.com",
"first": 10
}
}
{
"query": "query ListTemplates($first: Int!, $page: Int) { templates(first: $first, page: $page) { data { id name subject title is_system } } }",
"variables": {
"first": 10,
"page": 1
}
}
Before a mutation, show the user:
Mutation confirmation required:
- endpoint: https://api.example.com/graphql
- environment: staging
- company id: 123
- company branch id: branch-uuid
- app id: app-key-or-app-uuid
- user id: 456
- mutation name: createTemplate
- affected entity: Template
- variables:
{
"input": {
"name": "sales_assist_followup",
"parent_template_id": 0,
"template": "Hi {{first_name}},\nThanks for your interest.",
"template_variables": [
{ "key": "first_name", "value": "Lead first name" }
],
"title": "Sales Assist Follow-up",
"subject": "Following up",
"is_system": false
}
}
Reply with explicit confirmation to run this mutation.
Only after explicit confirmation:
curl -sS "$KANVAS_GRAPHQL_ENDPOINT" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-Kanvas-App: $KANVAS_APP_ID" \
-H "X-Kanvas-Key: $KANVAS_ADMIN_KEY" \
-H "X-Kanvas-Location: $KANVAS_COMPANY_BRANCH_ID" \
--data @- <<'JSON'
{
"query": "mutation CreateTemplate($input: TemplateInput!) { createTemplate(input: $input) { id name subject title } }",
"variables": {
"input": {
"name": "sales_assist_followup",
"parent_template_id": 0,
"template": "Hi {{first_name}},\nThanks for your interest.",
"template_variables": [
{ "key": "first_name", "value": "Lead first name" }
],
"title": "Sales Assist Follow-up",
"subject": "Following up",
"is_system": false
}
}
}
JSON
Prefer GraphQL variables instead of inline hardcoded values.
Keep these as runtime context or variables, never hardcoded:
Include branch/app/company/user context when required by the schema or operation. Many tenant-scoped models are app/company scoped even when the schema does not expose apps_id directly.
Before writes, verify target ids with a read query in the same context. For CRM/Guild flows, verify Leads, People, Organizations, Pipelines, Stages, Statuses, Sources, Owners, Receivers, and Branches before mutation.
Common payload structures:
input: create/update object for mutations.where: Lighthouse filter object.hasStatus, hasType, hasSource, hasOwner, hasCustomFields: relationship filters in CRM queries.orderBy: Lighthouse ordering object.search: full-text or model search string.first and page: pagination controls.custom_fields: list of custom field entity inputs.files: list of filesystem URL inputs or upload fields, depending on mutation.template_variables: list of { key, value } pairs.data, metadata, message: object payloads for notifications and engagement rules.Template and notification rules:
{{first_name}}.Common GraphQL naming conventions:
leads, people, templates, notifications.createX, updateX, deleteX, or domain-specific verbs.Input, such as LeadInput, LeadUpdateInput, TemplateInput.Always inspect:
dataerrorserrors[].messageerrors[].patherrors[].extensions, if presentSummarize useful data. Do not dump large raw responses unless explicitly requested.
Safe error summary:
GraphQL request failed:
- HTTP status: 200
- path: createTemplate
- message: Validation failed for the field [createTemplate].
- likely cause: missing required input field or invalid variable type
Never include full secrets from headers, variables, logs, Laravel traces, or response extensions.
Common interpretations:
Unauthenticated: missing/invalid bearer token, missing X-Kanvas-Key, expired app key, or a guarded field without valid user context.You are not authorized: user is not admin/owner, missing Bouncer ability, invalid scope, or field guarded by @guardByAdmin/@can.No Company Branched Specified: missing branch context, usually missing/invalid X-Kanvas-Location.No Company Branch configured with this key: invalid branch id/uuid in X-Kanvas-Location.No App configured with this key: invalid/missing X-Kanvas-App or deployment app config.No App Key configured with this key: invalid X-Kanvas-Key.App Key has expired: expired app key; request a valid key.Cannot query field: wrong field name, wrong endpoint/schema version, disabled module, stale schema cache, or wrong environment.Variable "$input" got invalid value: variables do not match the schema input type.Field ... argument ... is required: missing required argument or nested input field.$variables, or missing Content-Type.HTTP status handling:
200 with errors: GraphQL request reached the server; resolver, validation, auth, or scope failed.400: malformed JSON, invalid request body, missing query, invalid variables, or request size issue.401: missing/invalid auth.403: authenticated but unauthorized.404: wrong host, path, prefix, or GraphQL route.413: JSON or multipart request body too large.419: session/csrf mismatch on the wrong route or middleware path.429: throttled by GraphQL rate limiting.500: Laravel exception, invalid app/branch key handling, stale cache, dependency failure, or infrastructure issue.Request debugging checklist:
/graphql path.Content-Type: application/json and Accept: application/json.X-Kanvas-App selects the intended app.X-Kanvas-Location is the intended branch.query and object variables.<<'JSON' so shell does not expand GraphQL $variable names.Do not report a GraphQL request as failed only because the response contains null optional fields, empty arrays, warnings, or partial data.
Classify the result using this order:
Transport failure:
GraphQL execution failure:
errors existsdata is missing or nullPartial success:
data existserrors also existsSuccess:
data existserrorsBefore saying "the call failed", the agent must show:
data existserrors existsNever infer failure from:
errorsDocker/local debugging:
http://localhost:8000/graphql if Octane is published on port 8000.localhost..env app id/app key values match database records.Schema/cache debugging:
Cannot query field after deployment.Queue/cache debugging:
For the Intelligence FollowUp schema (graphql/schemas/Intelligence/followUp.graphql), use the dedicated runtime guide: FOLLOW_UP_GRAPHQL.md. It covers FollowUp, FollowUpDay, FollowUpTemplate queries, mutations, variables, cascade-delete risks, and Sales Assist CRM workflow safety.
For the Guild pipeline schema (graphql/schemas/Guild/pipeline.graphql), use the dedicated runtime guide: GUILD_PIPELINE_GRAPHQL.md. It covers LeadPipeline and LeadPipelineStage queries, mutations, variables, stage synchronization behavior, default-pipeline risks, delete guards, and CRM workflow safety.
For configuring Social messages with message type faqs, use the dedicated runtime guide: FAQ_MESSAGES_GRAPHQL.md. It covers finding or creating the faqs MessageType, creating JSON FAQ messages, update safety, public visibility, and duplicate prevention.
For the Social message schema (graphql/schemas/Social/message.graphql), use the dedicated runtime guide: SOCIAL_MESSAGE_GRAPHQL.md. It covers Message, MessageInput, MessageUpdateInput, message queries, mutations, distribution, interactions, file upload caveats, and destructive operation safety.
For the Guild lead receiver schema (graphql/schemas/Guild/leadReceiver.graphql), use the dedicated runtime guide: GUILD_LEAD_RECEIVER_GRAPHQL.md. It covers LeadReceiver queries, create/update/delete mutations, receiver templates, agent/source/type/rotation validation, webhook side effects, and branch safety.
For installing and maintaining Sales Assist handoff templates (lead_handoff, push, sms, and compliance variants) through graphql/schemas/Ecosystem/templates.graphql, use: HANDOFF_TEMPLATES_GRAPHQL.md.
For the general Ecosystem templates schema (graphql/schemas/Ecosystem/templates.graphql), use: ECOSYSTEM_TEMPLATES_GRAPHQL.md. It covers TemplateInput, template variables, parent templates, create/update/delete behavior, rendering, and admin safety.
For configuring Twilio or Mailgun inbound webhook receivers and AI Agent auto-reply workflow rules, use: AGENT_RESPONDER_RULES_GRAPHQL.md. It covers action discovery, Lead system module discovery, receiverWebhooks, createReceiverWebhook, connector settings, createRule/updateRule, verification, failure modes, and production guardrails.
For the Workflow webhook receivers schema (graphql/schemas/WorkFlow/receivers.graphql), use: WORKFLOW_RECEIVERS_GRAPHQL.md. It covers WorkflowReceiver, WorkflowReceiversHistory, createReceiverWebhook, updateReceiverWebhook, deleteReceiverWebhook, receiver status, webhook call history, async processing, and the distinction from Guild LeadReceiver.
Before request:
After response: