The open-source platform for human-agent collaboration in pharma
Define processes. Assign humans and AI agents to each step. Ship compliant workflows — fast.
Why Mediforce | How It Works | See It in Action | Get Involved
Pharma is ready for AI. The models are capable, the budgets exist, and the pressure to modernize is real. What's missing is the infrastructure — a way to deploy AI agents into regulated workflows with the compliance, auditability, and human oversight that GxP demands.
Mediforce is that infrastructure. Open-source, built for pharma, designed so your compliance team says yes on the first review.
One platform, every process. From clinical operations to pharmacovigilance to supply chain — define a process once, configure autonomy levels per step, and deploy. The first process is the hardest. Every one after that is incremental.
Your rules, your control. You decide how much autonomy each agent gets. An agent can draft and a human approves. Or the agent acts and a human reviews after the fact. The process stays the same; the configuration adapts to your organization's risk tolerance.
Compliance is not a bolt-on. Audit trails, accountability, data integrity, and scoped access are built into the platform from day one — not layered on top.
Read the full vision — why this needs to exist and where we're headed
Processes are made of steps. Each step can be performed by a human, an AI agent, or both — with clear rules about who decides what.
Every step is assigned a Control Mode (CM0–CM4) — the same picker used in the workflow designer's step-type popover:
| Mode | What it means |
|---|---|
No agent CM0 |
Human, script, or automated action - no AI involved. Full manual control. |
Assist CM1 (coming soon) |
Human leads and does the work; AI reviews the result afterward. |
Cowork CM2 |
Agent and human work together in real time, via chat or voice. |
Human review CM3 |
Agent completes the step; a human reviews and approves before the workflow proceeds. |
Autonomous agent CM4 |
Agent completes the step and the workflow advances on its own; a human can review after the fact via the audit trail. |
executor and autonomyLevel remain the underlying schema fields (unchanged); Control Mode is a UI-only classification layered on top — see docs/design/AUTONOMY-LEVELS-REFACTOR.md.
At any mode, an agent can signal uncertainty and escalate to a human. This isn't a failure mode — it's how the system maintains safety in production.
These aren't chatbots. Mediforce agents perform real cognitive work inside structured processes:
- Document analysis — review consent forms, flag missing fields, simplify language
- Anomaly detection — monitor metrics, alert on unusual patterns across sites
- Report generation — draft clinical summaries, compile safety narratives
- Supply intelligence — forecast demand, detect risk signals, optimize inventory
- Quality checks — validate data integrity, cross-reference against standards
Every agent operates under human oversight, with every action recorded in a complete audit trail.
All your workflows in one place — run counts, active status, and one-click access to any process execution.
The core decision point. Reviewers see full context from the agent's work and submit their verdict — approve, revise, or escalate.
In regulated industries, trust and transparency are non-negotiable. Open source is the right model:
- Full transparency — your compliance team can inspect every line of code
- Zero vendor lock-in — you own your deployment, your data, your customizations
- Shared standard — instead of every company building their own AI integration layer, we build one together
- Community-driven quality — battle-tested by the people who use it
We're Appsilon — we've been building open-source tools for life sciences for over a decade. Mediforce applies that same philosophy to the biggest opportunity in pharma today.
We're building the standard for human-agent collaboration in pharma — and we're doing it in the open.
- Getting Started — set up your development environment
- Join our Discord — follow progress, ask questions, shape the roadmap
- Star this repo — helps others in pharma find us
- Open an issue — tell us what processes matter most to you
Getting Started Guide — Quick start with emulators and demo data, no setup required.
Datastore (ADR-0001). Server data layer runs on self-hosted Postgres. See
docs/postgres-local-dev.mdanddocs/adr/0001-firestore-to-postgres.md.
pnpm install
pnpm dev:mock # port 9007, mocked agents, local emulators + demo dataOpen http://localhost:9007. Use this to click through the UI without configuring a Firebase project, cloud keys, Docker, or real agents.
| Command | What it gives you |
|---|---|
pnpm dev |
Default full local stack. Boots a local Postgres via the docker overlay, runs migrations, then starts the UI; agents run inline via Docker (no Redis). Firebase Auth/Storage + the users/{uid} profile collection still come from .env.local. The main dev loop. |
pnpm dev:mock |
Mocked agents + seeded local emulator data, port 9007. No cloud keys, no Docker, no Firebase project. |
pnpm dev:no-docker |
Docker-free, UI-only. Agents run via host claude CLI instead of Docker. |
pnpm dev:queue |
Like dev, but agent execution goes through the BullMQ queue (production architecture). Boots redis alongside Postgres; requires the worker running — see below. |
Bring up Postgres and point the app at it. One command does all of the above:
pnpm dev # docker compose up + migrate + devManual equivalent if you need to wire your own env (e.g. point at an external Postgres):
docker compose up postgres -d # boot Postgres 16
# in packages/platform-ui/.env.local:
# DATABASE_URL=postgresql://mediforce:mediforce@localhost:5432/mediforce
pnpm db:migrate # apply Drizzle migrations once
pnpm dev # start the apppnpm db:migrate is idempotent — re-run after pulling new migrations
from main. Same script runs inside pnpm dev and inside the
production Dockerfile's CMD, so dev and prod share the migration path.
See Staging / production ops below.
Firebase Auth is still required (until ADR-0002 lands a NextAuth
replacement); set the NEXT_PUBLIC_FIREBASE_* vars in .env.local as usual.
Firebase Emulators are not required for the Postgres data path — only for
the auth flow if you don't want to use a real Firebase project.
Migration mechanics, schema authoring, and troubleshooting live in
docs/postgres-local-dev.md.
docker-compose.yml runs Postgres + Redis + container-worker + bull-board (BullMQ UI on :3100):
docker compose up -d # bring up queue infra
pnpm dev:queue # native UI pointed at compose Redis
docker compose down # stop infra when you're donecp packages/platform-ui/.env.example packages/platform-ui/.env.local
pnpm emulators # terminal 1
pnpm seed # terminal 2 — seeds demo workflows + data
NEXT_PUBLIC_USE_EMULATORS=true pnpm dev # terminal 2Demo credentials: test@mediforce.dev / test123456. For production Firebase setup, see the Getting Started Guide.
pnpm typecheck # type checking (~5s)
pnpm test:unit # vitest L1+L2 (~9s)
pnpm test:affected # vitest, only files changed since main (<1s)
pnpm test:e2e # Playwright L3+L4 (~4min, requires Firebase emulator)
pnpm test # everything: test:unit + test:e2eE2E variants:
pnpm test:e2e:api # L3 only — API E2E, no browser (~30s)
pnpm test:e2e:ui # L4 only — UI E2E with real ChromiumFor UI-only journeys, run pnpm test:e2e --project=authenticated from the platform-ui directory (or invoke Playwright's interactive UI mode via pnpm test:e2e:ui there).
@mediforce/cli is a thin wrapper around the platform API for registering
workflows, starting runs, and inspecting state from a terminal. The bin
entry runs tsx against src/, so changes show up without a build.
Run it from the workspace so it always uses the checked-out source:
pnpm exec mediforce --helpAuth + base URL come from env. Add to ~/.zshrc (or the per-shell
session) so every invocation picks them up:
export MEDIFORCE_API_KEY="<value of PLATFORM_API_KEY in .env.local>"
export MEDIFORCE_BASE_URL="http://127.0.0.1:9003"
# Use 127.0.0.1 not localhost — Node prefers IPv6 and the dev server
# binds IPv4, which surfaces as a misleading "fetch failed".Common commands:
pnpm exec mediforce workflow list # all registered workflows
pnpm exec mediforce workflow register --file path/to.wd.json --namespace appsilon
pnpm exec mediforce run start --workflow landing-zone-CDISCPILOT01 --namespace appsilon
pnpm exec mediforce run get <runId> # current status
pnpm exec mediforce <command> --help # per-command flagsWorkflows with script executor steps need Docker images built locally — none
are pulled from a registry. Build everything in one go:
./scripts/rebuild-docker-images.shThis builds mediforce-golden-image and mediforce-node (used by most inline
runtime: javascript script steps, and as the fallback when a step omits
agent.image), plus the per-app images (community-digest, protocol-to-tfl,
tealflow, landing-zone).
Skip this if you only use human or agent executor steps, or run with MOCK_AGENT=true.
By default, agents execute inside Docker containers. To run them using your local claude CLI instead (useful for development and reducing costs):
pnpm dev:no-dockerRequires
claudeto be available on yourPATH. Use this script (notALLOW_LOCAL_AGENTS=true pnpm dev) — the env var doesn't propagate reliably through pnpm script aliases.
Full guide: docs/development.md
docker-compose.prod.yml ships a postgres:16-alpine service alongside
Redis. The host needs two things before platform-ui will start:
POSTGRES_PASSWORDset in/opt/mediforce/.env(no default — required).POSTGRES_USER+POSTGRES_DBdefault tomediforce./var/lib/mediforce/postgres-dataexists on the host, owned by UID 999 (the postgres-alpine user).docker-compose.staging.ymlbind-mounts that path sodocker compose down -vcannot wipe data — only an explicitrm -rfremoves it. Local dev keeps a named volume, sodocker compose down -vis still a normal reset workflow on a developer machine.
Fresh server provisioning is handled by
scripts/bootstrap-server.py: it
auto-generates POSTGRES_PASSWORD (per ADR-0001, PR #559) and creates
the bind-mount data dir with the right ownership as part of its
step_env_local + step_postgres_dir flow on a new host.
Already-bootstrapped deployments (the current staging) — bootstrap
is not re-run against them. Add POSTGRES_PASSWORD + create the dir
manually via ssh.
Drizzle migrations run in a short-lived migrate compose service (init
container, see docker-compose.prod.yml)
before platform-ui starts. platform-ui waits via
depends_on: { migrate: { condition: service_completed_successfully } }.
Idempotent (drizzle's __drizzle_migrations ledger). No separate
migration step in the deploy pipeline.
| Getting Started | Set up your development environment — local Postgres data layer plus Firebase Auth/Storage |
| Vision | Why this needs to exist, what agents actually do in pharma, and where we're headed |
| Architecture | Processes, steps, agents, compliance — the technical foundation |
| How We Work | Building bottom-up, in public, with real processes |
| Development | Setup, monorepo structure, testing, deployment |
Apache License 2.0 — see LICENSE.
Built by Appsilon — data solutions for life sciences since 2013.

