Waleed d374ebce6f fix(webhooks): accept the methods and expose the request metadata the generic webhook advertises (#6893)
* feat(webhooks): support query parameters and GET deliveries on generic webhooks

The generic webhook Setup Instructions promised that query parameters would be
available in the workflow and that any HTTP method would be accepted, but
neither was true: query parameters were never carried past the route, and every
GET that was not a provider challenge got a 405.

Carry the request query string into the execution payload and expose it to
providers through FormatInputContext. The generic provider merges it into the
workflow input under a reserved `query` key, leaving the body's own fields
untouched so existing payloads resolve exactly as before.

Add an opt-in `acceptsGetDelivery` provider capability and enable it for the
generic provider, so a workflow can be triggered by a plain URL fetch such as a
link in an email. Providers that have not opted in still answer 405, and unknown
paths keep answering 405 on GET so probes cannot distinguish them.

Update the Setup Instructions to describe what the endpoint actually accepts.

Signed-off-by: mini.jeong <mini.jeong@navercorp.com>

* feat(webhooks): expose generic webhook request headers

The generic webhook's Setup Instructions promised that request headers would be
available in the workflow, but formatInput returned only the body: headers were
used solely for the idempotency key and provider signature checks.

Expose them under a reserved `headers` key, withholding the ones that carry
credentials. Exposing a credential would copy it into execution logs and trace
spans, where it outlives the request, so a fixed denylist (authorization,
cookie, x-api-key, ...) is combined with the webhook's own configured
secretHeaderName. A denylist rather than an allowlist keeps arbitrary custom
headers usable, which is the point of the feature.

Generalize the query-parameter merge so query and headers share the same
key-wise body-precedence rule.

Also correct the authentication instruction: only the configured method is
accepted, not either one.

Refs #6888

Signed-off-by: mini.jeong <mini.jeong@navercorp.com>

* feat(webhooks): accept PUT, PATCH and DELETE deliveries and expose the request method

The generic webhook's Setup Instructions promised any HTTP method, and the /api
CORS policy already advertises PUT, PATCH and DELETE, yet the route answered 405
for everything except POST and GET. Open the remaining methods for providers that
opt in, which today is only the generic webhook.

Expose the method on the trigger input as well. Without it a workflow behind one
URL cannot tell a create from a delete, which makes multi-method delivery half a
feature. The payload field is optional so jobs already queued at deploy time keep
executing.

Turn the GET-only opt-in into a per-provider method set, and let the request
metadata merge carry scalar values so `method` follows the same key-wise
body-precedence rule as query and headers.

Refs #6888

Signed-off-by: mini.jeong <mini.jeong@navercorp.com>

* feat(webhooks): declare the generic webhook trigger outputs

The trigger declared no outputs, so the reference dropdown in the editor offered
no completions for it and users had to type paths like `query.id` by hand after
reading the setup instructions. Declare the request metadata that is known ahead
of time. Body fields stay undeclared because a generic webhook receives whatever
JSON the caller sends.

Refs #6888

Signed-off-by: mini.jeong <mini.jeong@navercorp.com>

* fix(webhooks): stop provider challenges from intercepting other providers' deliveries

The challenge handlers run before webhook lookup and are provider-blind, so two
query parameter names are effectively reserved across every path. Now that a
generic webhook can be triggered by a URL fetch, a link carrying either name
answers the challenge instead of running the workflow:

- `?validationToken=x` is echoed back as a Microsoft Graph subscription
  validation. Graph sends that validation as a POST, so ignore the parameter on
  every other method.
- `hub.mode`, `hub.verify_token` and `hub.challenge` answer 403 when no WhatsApp
  webhook on the path expects a token. A path with no such webhook is not a
  failed verification - the parameters belong to whoever owns that path - so fall
  through and let the delivery route normally. A token mismatch against a
  WhatsApp webhook still fails with 403.

Refs #6888

Signed-off-by: mini.jeong <mini.jeong@navercorp.com>

* fix(webhooks): make the request metadata opt-in per webhook

The four commits below make the generic webhook do what its Setup Instructions
promise. They do it through a provider-level capability, which applies to every
generic webhook row the moment it deploys: each one begins accepting GET, PUT,
PATCH and DELETE, and each one's workflow input gains `method` and `headers`,
on POST deliveries too. No webhook owner chose either.

Gate both behind `providerConfig` flags written by two switches, off by default.
A webhook deployed before these existed has neither flag, so it answers POST
only and its input is exactly the body, as before. `query` stays ungated: it is
dropped today, only appears when the caller's own URL carries it, and yields to
a body field of the same name.

Generalize the Microsoft Teams challenge fix. Every challenge handler runs
before the webhook lookup and matches on payload shape alone, so any of them
will answer a delivery addressed to another provider on the same path. Gate
them centrally to POST via `challengeMethods`, which WhatsApp widens to GET for
Meta's handshake, rather than guarding one handler inline.

Also:

- Widen the credential header denylist to 24 names and withhold the webhook's
  own token by value as well as by name, since a denylist is leaky by
  construction.
- Condition the `method` and `headers` trigger outputs on their switches, so
  the reference dropdown cannot offer a field the webhook will not send.
- Give PUT, PATCH and DELETE their own contracts instead of reusing the POST
  one, whose `method: 'POST'` had become untrue.
- Parse, challenge and generate a request ID once per delivery rather than
  twice on GET, which was logging one request under two IDs.
- Offer the challenge handlers the request before admission, so Meta's GET
  handshake cannot be answered with a 429 by a busy instance.
- Answer every non-POST rejection with the same 405 plus `Allow`, whether the
  path is unknown, holds only non-path triggers, or holds a trigger that has
  not opted in.
- Read flags through a helper treating only `true`/`'true'` as on: the editor
  writes booleans, but a YAML- or Copilot-authored workflow can write the
  string `'false'`, which is truthy.
- Name the methods switch "Accept Other HTTP Methods": HEAD and OPTIONS still
  answer 405, so claiming "all" would reintroduce the overstatement this whole
  change set exists to remove.
- Drop the per-delivery metadata warn logs to debug.

---------

Signed-off-by: mini.jeong <mini.jeong@navercorp.com>
Co-authored-by: mini.jeong <mini.jeong@navercorp.com>
2026-08-20 14:38:08 -07:00
2026-08-20 14:05:46 -07:00

Sim.ai Documentation Slack X

Ask DeepWiki Set Up with Cursor

Sim — Integrate, Context, Build, and Monitor AI agents

A workspace to build, deploy and manage AI agents and workflows.

Quickstart

Cloud-hosted: sim.ai

Open sim.ai

Self-hosted

npx sim-setup

Open http://localhost:3000

The Sim platform — chat on the left, the visual workflow builder on the right

Capabilities

  • Connect 1,000+ integrations and every major LLM
  • Add Slack, Notion, HubSpot, Salesforce, databases, and more
  • Build agents visually, conversationally, or with code
  • Ingest files, knowledge bases, and structured table data
  • Monitor runs, logs, schedules, and workflow activity

One workspace, every surface

Chat and workflows are just the start — tables, files, and knowledge all live in the same workspace.

Tables in Sim — structured data your agents can query

Tables — a database, built in

Files in Sim — documents for your team and every agent

Files — one store for your team and every agent

Knowledge bases in Sim — synced docs your agents can search

Knowledge — your agents' memory

Self-hosting

Requirements: Node.js 20+ and Docker.

npx sim-setup is an interactive wizard that creates a small sim/ deployment directory, provisions the database, generates secrets, writes .env, connects a Chat API key, and starts the published Sim images with Docker Compose. It does not clone the repository.

When it finishes, open http://localhost:3000.

Inside a cloned Sim repository, run bun run sim-setup to unlock the source-only local development and Kubernetes modes.

Reconfigure an optional capability without rerunning the full wizard:

npx sim-setup config
npx sim-setup add email
npx sim-setup add storage
npx sim-setup add sandbox
npx sim-setup add jobs
npx sim-setup add cache
npx sim-setup add knowledge
npx sim-setup add llm
npx sim-setup add integration slack

npx sim-setup config detects the effective local-dev, Docker Compose, or current-context Helm configuration and reports configured, missing, or invalid capabilities and OAuth integrations without printing credential values. This is separate from npx sim-setup status, which reports whether installed services are running and healthy.

Manage your install from its directory:

npx sim-setup start | stop | restart   # bring your install up / down / cycle
npx sim-setup update                   # pull and apply Compose images
npx sim-setup status                   # what's installed and healthy
npx sim-setup logs                     # follow logs
npx sim-setup doctor                   # diagnose configuration problems
npx sim-setup down                     # remove containers (data kept)
npx sim-setup reset                    # archive .env and wipe managed data

The setup package detects how you're running and acts accordingly. Use --dir <path> to create or manage a deployment somewhere other than ./sim.

Sim also supports local models via Ollama and vLLM. See the self-hosting docs for details.

Chat API Keys

Chat is a Sim-managed service. npx sim-setup connects a Chat API key for you — sign in when it opens your browser and the key is stored automatically. To view, create, or revoke keys later, go to sim.ai/selfhost/settings/chat-keys.

Environment Variables

See the environment variables reference for the full list, or apps/sim/.env.example for defaults.

Tech Stack

Next.js · Bun · PostgreSQL · Drizzle · Better Auth · Tailwind — and the rest of the stack

Contributing

We welcome contributions! Please see our Contributing Guide for details.

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Built by the Sim team in San Francisco

Languages
TypeScript 77%
MDX 20.8%
JavaScript 1.9%
CSS 0.1%