Skip to content
HaneDOCS日本語

Build apps

Writing manifests

The common shape of manifests (YAML), the kinds of definitions, file layout, validation, and CEL expressions.

This page explains how to write Hane definitions as manifests. Manifests are YAML files kept in Git. When you apply them with hanectl they become drafts, and they take effect when you activate a ReleaseBundle. The concepts behind definitions are covered in Definitions and releases.

Every manifest has four parts: apiVersion, kind, metadata, and spec.

apiVersion: data/v1alpha1 # format version (<group>/v1alpha1)
kind: Rule # kind of definition
metadata:
name: lease-end-date # lowercase letters, digits, hyphens. Up to 63 characters
annotations:
description: Calculates the end date from the start date and the term in months
spec:
target: LeaseContract
field: end_date
inputs: [start_date, term_months]
expr: addDays(addMonths(record.start_date, record.term_months), -1)
  • Don’t write status or the revision in the file. Hane adds them on every apply.
  • Each kind’s spec is defined by a JSON Schema, and unknown keys are rejected.
  • You can put several manifests in one file, separated by ---.
apiVersion kind What it defines
data/v1alpha1 Schema, Ontology, Rule, Calculation, Migration, Axiom, Aspect Types and fields, relations, rules and calculations, field renames and type changes, business knowledge and aspects
workflows/v1alpha1 Workflow, Schedule How cases proceed, and daily triggers
approvals/v1alpha1 AssignmentRule, DeciderPolicy Task assignment, and who decides external actions
agents/v1alpha1 Agent, EvalSuite, TriageRule Agents, evaluations, triage rules
documents/v1alpha1 DocumentType, ExtractionSchema, DocumentSource Document types, extraction schemas, external storage
communication/v1alpha1 SenderIdentity, ContactPolicy, ContactRetention, CallBriefTemplate Sender identities, contact policies, contact retention, call brief templates
integrations/v1alpha1 Connection Connections to external systems
gateway/v1alpha1 Route, PublishedApi, ToolExposure, Consumer Routes to your APIs, and exposing them as agent tools
browser/v1alpha1 BrowserFlow Steps for operating a portal
platform/v1alpha1 Budget, RoleBinding, GitSource Budgets, role bindings, syncing from Git
release/v1alpha1 EnvironmentBinding, SourcePolicy Names that differ per environment, rules for where definitions come from
factory/v1alpha1 Application Apps served by Hane

The following kinds are settings. They are not bundled into a ReleaseBundle and take effect as soon as you apply them in each environment: Consumer, ContactRetention, DocumentSource, EnvironmentBinding, GitSource, RoleBinding, SenderIdentity, SourcePolicy. All other kinds become drafts and don’t take effect until a ReleaseBundle is activated. After apply, hanectl tells you which happened.

Put each kind in its own directory, and list what goes into the ReleaseBundle in bundle.yaml. Bundle is read only by hanectl and is not sent to Hane.

  • Directorydefinitions/
    • bundle.yaml
    • Directoryschemas/
      • vehicle.yaml
      • lease-contract.yaml
    • Directoryrules/
      • …
    • Directoryworkflows/
      • …
    • Directoryschedules/
      • …
    • Directorypolicies/
      • …
    • Directoryagents/
      • …
    • Directorysenders/ settings; not listed in bundle.yaml resources
      • …
apiVersion: release/v1alpha1
kind: Bundle
metadata:
name: vehicle-lease
spec:
resources:
- schemas/
- rules/
- workflows/
- schedules/
- policies/
- agents/

When you add a directory for a new kind, add it to resources too. If you forget, apply still succeeds, but the definitions are not included in the ReleaseBundle and never take effect.

When Where What is checked
hanectl validate -f <dir> Locally Shape (JSON Schema), references between definitions, CEL expressions. Secret names and term collisions are reported as warnings
hanectl diff -f <dir> Hane What apply would change. Flags changes such as widening what AI may approve
hanectl apply -f <dir> Hane Runs the same checks on the server, and saves drafts if they pass
Activating a ReleaseBundle Hane Whether per-environment names (EnvironmentBinding) resolve, and in stage and prod, whether evaluations (EvalSuite) pass

Local validation uses the same checks as Hane, so running hanectl validate in CI catches mistakes before apply.

Conditions and calculations are written in CEL. Expressions are limited to 1,000 characters and cannot use the current time, random numbers, or external reads and writes. The same input always produces the same value.

Where Variables
Rule expr record (input fields only)
Schedule forEach.where record, states, event (event.date is the trigger date)
Workflow expressions (titles, branches, due dates, and so on) subject, states, case, steps, input
where of GET /v1/data/records record, states

Calendar dates are YYYY-MM-DD strings, calculated with these functions:

Function What it does
addDays(date, n), addMonths(date, n) Adds days or months to a date
daysBetween(a, b) Days between two dates
isDate(v) Whether a value is a date string
zonedDate(time, zone) Converts a recorded time into a calendar date in a time zone
minOf(a, b) The smaller of two values
moneyText(m) Formats an amount with the currency’s decimal places
# Every morning, open a case for each active contract whose notice deadline is within 90 days
apiVersion: workflows/v1alpha1
kind: Schedule
metadata:
name: daily-expiry-scan
spec:
every: day
at: "07:00"
timezone: Asia/Tokyo
forEach:
type: LeaseContract
where: record.status == "active" && record.notice_due != null && daysBetween(event.date, record.notice_due) <= 90
workflow: lease-expiry

states holds each field’s value state (confirmed, estimated, pending_inquiry, unknown). To stop a process from moving on with unconfirmed values, branch on something like states.end_date != "confirmed".