Skip to main content

Metis Workflow

metis-workflow is a small Python framework for workflows powered by TypeSafe AI's Jev model. Define a workflow class, use integrations where needed, and compose named steps. Python 3.10+, no runtime dependencies.

Package Location Purpose
metis-workflow Repository root Framework, CLI, GitHub Action, and integrations
metis-triage legacy/metis-triage/ Archived standalone issue-triage package

The framework imports as metis_workflow. Both issue triage and PR screening are examples built entirely with this framework. They do not import the legacy package. The current framework version is 0.1.0.

Guides: Migration · Custom workflows.

Install

From this checkout:

python -m pip install .

After publication, the distribution can be installed with pip install metis-workflow.

Define a workflow class

from metis_workflow import Step, Workflow
from metis_workflow.integrations import Jev

class SupportRouting(Workflow):
    name = "support-routing"

    def build_steps(self):
        return (
            Step("assess", self.assess),
            Step("route", self.route),
        )

    def assess(self, ctx):
        jev = ctx.integrations.setdefault("jev", Jev())
        return jev.check(ctx.event, {
            "billing": "Does this ticket concern a payment or invoice?"
        })

    def route(self, ctx):
        value = ctx.outputs["assess"]["billing"]
        return {"queue": "billing" if value >= 0.8 else
                "support" if value <= 0.2 else "manual-review"}

workflow = SupportRouting

Export the class as workflow to run it from the CLI. In application code, use SupportRouting().run(event={"message": "I was charged twice"}).

Workflow owns execution, skips, error handling, and the run report. Define the order in build_steps() and change behavior by overriding individual methods. Each step's return value is available by name in ctx.outputs.

Context field Purpose
event Input for this run
config Workflow defaults merged with supplied settings
integrations API clients shared by the steps
state Internal run data, omitted from the run report
outputs Named step results included in the run report
dry_run Whether write steps should suppress external changes

Override default_config() and validate_config(config) to define and check settings. Pass overrides to the constructor or .run(config={...}). Each run gets fresh state and outputs and a copy of its configuration. Supply clients with SupportRouting(integrations={"jev": Jev(...)}) or .run(integrations={...}).

Use Step("notify", self.notify, when=lambda ctx: ...) for conditional steps. Call ctx.skip("reason") to stop the workflow normally. Errors stop subsequent steps. Write steps must honor ctx.dry_run; return only data suitable for the run report. Override matches(event, event_name=None) to control event dispatch. Workflows run sequentially in one process; scheduling comes from the caller or GitHub Actions.

Integrations

src/metis_workflow/integrations/ contains the shared clients:

  • GitHub(repository, token=None, dry_run=False) reads repository API endpoints, follows paginated lists, and supports explicit writes.
  • Jev(api_key=None, model=None) supplies typed judgments. check(state, criteria) returns yes/no probabilities for a checklist. evaluate(state, questions) runs Choice, Noul, and Score questions together and validates the returned answers. Question and answer shapes follow the TypeSafe API.

GitHub credentials default to GITHUB_TOKEN. Jev credentials default to TYPESAFE_API_KEY, and the model defaults to TYPESAFE_DEFAULT_MODEL or jev-latest. The workflow owns thresholds, policies, and actions; integrations own API calls.

Examples

src/metis_workflow/
  workflow.py             Workflow, Step, and Context
  runner.py               Event dispatch
  integrations/
    github.py             GitHub API client
    jev.py                Typed Jev judgments
examples/
  issue_triage.py         IssueTriage(Workflow)
  issue_triage.json       Label names and triage thresholds
  pr_screening.py         PRScreening(Workflow)
  pr_screening.json       PR criteria and screening policy
  support_routing.py      SupportRouting(Workflow)
legacy/metis-triage/       Independent archived package

Copy an example and its companion JSON to customize it. Both GitHub examples read defaults from the JSON next to their Python file. They use the same public framework and integrations available to any user workflow.

Example Steps Result
Issue triage load → classify → label → reply Labels issues and requests missing bug details
PR screening load → evidence → judge → apply Screens external contributions and closes clear failures
Support routing assess → route Chooses a support queue and priority

Issue triage classifies new issues as bug, feature, documentation, question, or other. It applies existing labels only after configured confidence and probability thresholds pass. For clear bugs, it posts a fixed template listing missing reproduction, behavior, or environment details. It skips uncertain results, bot-authored or oversized issues, changed text, conflicting category labels, previous Metis replies, and conversations a person has already joined. It does not create labels or close issues. Default label names are bug, enhancement, documentation, and question; configure names that exist in your repository.

PR screening exempts the repository owner and owning organization's members, bots, drafts, and configured author exemptions. It reads the title, body, patches, repository description, and README at the trusted base commit. The default checks are relevance, a concrete useful change, and absence of promotional spam. No linked issue is required; small fixes and documentation improvements count.

Passing and uncertain PRs stay open. A criterion probability at or below 0.05 allows closure; all probabilities at least 0.8 count as passing. Missing, binary, or incomplete patches and oversized PRs need manual review. These are initial policy thresholds, not evaluated accuracy guarantees. The workflow rechecks PR state before writing, posts a configured explanation, and closes clear failures. There remains a small race between the final read and GitHub's close request. Reopened PRs are screened again; use an author exemption to exclude a contributor from future screening.

Run workflows

metis-workflow run --workflow-file examples/support_routing.py --event ticket.json
metis-workflow run --workflow-file examples/issue_triage.py --event issue-event.json --dry-run
metis-workflow run --workflow-file examples/pr_screening.py --event pr-event.json --dry-run

--event supplies a JSON input object. For a single class file, --config path.json overrides its defaults. A dry run still reads GitHub and calls Jev; the examples suppress writes when dry_run is true. Loading a workflow file executes trusted local Python.

For several workflows, create a manifest such as .github/metis-workflows.json:

{
  "version": 1,
  "workflows": [
    {"name": "issue-triage", "file": "../examples/issue_triage.py"},
    {
      "name": "pr-screening",
      "file": "../examples/pr_screening.py",
      "config": {"repository_context": "We accept bug fixes, examples, and docs improvements."}
    }
  ]
}

Entries contain a unique name, a file relative to the manifest, and optional enabled and config fields. Settings override top-level defaults; a criteria object replaces the complete checklist. All workflows use this same file-based registration; the framework has no built-in use cases or legacy adapters.

metis-workflow list --manifest .github/metis-workflows.json
metis-workflow run --manifest .github/metis-workflows.json --workflow issue-triage --event issue-event.json

The dispatcher calls each class's matches() method. python -m metis_workflow uses the same CLI.

GitHub Action

Copy the examples, companion JSON files, and manifest into your repository. Add the following workflow on the default branch and configure TYPESAFE_API_KEY as a repository secret. Pin a published commit containing this framework for reproducible use; main is the development reference.

name: Metis workflows
on:
  issues:
    types: [opened]
  pull_request_target:
    types: [opened, reopened, synchronize, edited, ready_for_review]

permissions:
  contents: read
  issues: write
  pull-requests: write

concurrency:
  group: metis-${{ github.repository }}-${{ github.event.issue.number || github.event.pull_request.number }}
  cancel-in-progress: false

jobs:
  run:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          ref: ${{ github.event.pull_request.base.sha || github.sha }}
          persist-credentials: false
      - uses: Ayush0054/metis@main
        with:
          manifest-path: .github/metis-workflows.json
          typesafe-api-key: ${{ secrets.TYPESAFE_API_KEY }}

Use workflow to select a name from the manifest. To run one class directly, set workflow-file: examples/issue_triage.py and optional config-path instead of manifest-path. dry-run: 'true' asks the workflow to evaluate without writes. The optional github-token and model inputs replace the default GitHub token and Jev model. A write error can leave a partial action; inspect or rerun the job.

Only trusted base code and configuration should execute in pull_request_target. PR head code must never be checked out or run in this privileged job. See GitHub's trigger documentation. Issue text, PR text, and patches are sent to TypeSafe for evaluation.

Legacy package

legacy/metis-triage retains the original package at version 0.1.0, with its own metadata, source, README, and license. It can be installed independently. It has no dependency on the new framework, and the new framework and examples have no dependency on it. New work belongs in metis-workflow and the examples.

Publishing

.github/workflows/publish.yml builds only the root metis-workflow distribution and publishes through PyPI Trusted Publishing. Configure the publisher for project metis-workflow, owner Ayush0054, repository metis, workflow publish.yml, and environment pypi-workflow. A release tag must match the root package version, currently v0.1.0. The legacy package has no automated publication in this workflow.

Design references

The class API draws on Temporal workflow classes, step composition on Agno workflows, and explicit execution state on Prefect flows.

License

MIT © 2026 Ayush Jha.

Metadata

Release files for metis-workflow 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for metis-workflow 0.1.0
File Size Uploaded Provenance Actions
metis_workflow-0.1.0.tar.gz 20.1 kB With provenance Details for metis_workflow-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for metis-workflow 0.1.0
File Interpreter ABI Platform Actions
metis_workflow-0.1.0-py3-none-any.whl Python 3 none any Details for metis_workflow-0.1.0-py3-none-any.whl

Total release size: 36.6 kB

Release files / metis_workflow-0.1.0.tar.gz

Download URL metis_workflow-0.1.0.tar.gz
Size 20.1 kB
Tags Source
SHA-256 checksum
How to use checksums
1ebbda02712439c87c1a8126cb80a88a0d7cf15940a9349788883129d1251895
BLAKE2b-256 checksum
How to use checksums
a5e1a74edb86b8468ca9c6887549efbf61b63dac7c348068c993774516aa0719
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / metis_workflow-0.1.0-py3-none-any.whl

Download URL metis_workflow-0.1.0-py3-none-any.whl
Size 16.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e926a534827620b985af0a022e7b7130c33281a38e265c0c8c042c83e8add046
BLAKE2b-256 checksum
How to use checksums
e0ed5ed3bbaa051bfdd23bf9576614533a3aa6d78f8754cc386739e60f5b9b95
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Security for metis-workflow 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for metis_workflow-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page