* 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>
A workspace to build, deploy and manage AI agents and workflows.
Quickstart
Cloud-hosted: sim.ai
Self-hosted
npx sim-setup
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 — a database, built in |
Files — one store for your team and every agent |
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
- Framework: Next.js (App Router)
- Runtime: Bun
- Database: PostgreSQL with Drizzle ORM
- Authentication: Better Auth
- Schema Validation: Zod
- UI: Shadcn, Tailwind CSS
- Streaming Markdown: Streamdown
- State Management: Zustand, TanStack Query
- Flow Editor: ReactFlow
- Docs: Fumadocs
- Monorepo: Turborepo
- Realtime: Socket.io
- Background Jobs: Trigger.dev
- Remote Code Execution: E2B
- Isolated Code Execution: isolated-vm
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.




