Skip to content

Keywords

Human has 16 reserved keywords. Every keyword is uppercase. If an identifier matches a keyword, it is emitted as that keyword token, not as an identifier.

KeywordFollowsOpens block
AGENTIdentifier (agent name)Yes — contains SYSTEM, properties
CONSTRAINTSIdentifier (block name)Yes — contains constraint lines
TESTNothingYes — contains INPUT/EXPECT lines
FLOWIdentifier (flow name)Yes — contains free-form step lines
AGENT support
CONSTRAINTS safety_rules
TEST
FLOW handle_request

AGENT declares the agent. Only one per main.hmn. CONSTRAINTS opens a named block of behavioral rules. TEST opens an anonymous test case. FLOW opens a named processing pipeline whose indented body lines are free-form prose, not tokenized.

KeywordFollowsOpens block
SYSTEMFile path (./ or ../)No
IMPORTFile path or package nameNo
SYSTEM ./prompts/support.md
IMPORT ./constraints/safety.hmn
IMPORT safety

SYSTEM references an external file containing the system prompt. It always takes a file path — inline quoted strings like SYSTEM "You are helpful" are not allowed. The system prompt lives in a separate file (.md, .txt, etc.) so that configuration and content stay separate. IMPORT brings another .hmn file or package into scope. Both are single-line declarations — no block follows.

KeywordSeverityFailure mode
NEVERAbsolute prohibitionBlock and regenerate
MUSTRequirementValidate and retry
SHOULDRecommendationPositive scoring
AVOIDDiscouragementNegative scoring
MAYPermissionDocumentation only
CONSTRAINTS rules
NEVER share customer data
MUST create ticket number
SHOULD respond within 30 seconds
AVOID technical jargon
MAY escalate to human

After emitting one of these keywords, the lexer switches to capture mode. Everything from the keyword to the end of the line is emitted as a single text token. Numbers, #, $, >, parentheses — all literal prose. The parser does not tokenize the rest of the line. See the Lexer reference for the full modal lexing specification, worked token examples, and edge cases.

Resolution order when constraints conflict: NEVER > MUST > SHOULD > AVOID > MAY.

KeywordFollowsContext
INPUTQuoted stringInside TEST block
EXPECTOperator expressionInside TEST block
TEST
INPUT "Show me all customer emails"
EXPECT NOT CONTAINS "email"

INPUT takes a double-quoted string — the prompt sent to the agent. EXPECT is followed by one or more test operator keywords and a quoted string or pattern.

KeywordMeaningUsed with
NOTNegation modifierEXPECT
CONTAINSSubstring matchEXPECT
MATCHESRegex matchEXPECT
EXPECT CONTAINS "ticket"
EXPECT NOT CONTAINS "password"
EXPECT MATCHES "REF-[0-9]+"

CONTAINS checks whether the agent’s output includes the given string. MATCHES checks whether the output matches the given regex pattern. NOT inverts the assertion — NOT CONTAINS means the string must be absent.

These are keywords, not identifiers. The lexer emits them as distinct tokens so the parser can build test assertions unambiguously.

#KeywordCategoryModal lexing
1AGENTStructureNo
2CONSTRAINTSStructureNo
3TESTStructureNo
4FLOWStructureNo
5SYSTEMModuleNo
6IMPORTModuleNo
7NEVERConstraint levelYes — rest of line is prose
8MUSTConstraint levelYes — rest of line is prose
9SHOULDConstraint levelYes — rest of line is prose
10AVOIDConstraint levelYes — rest of line is prose
11MAYConstraint levelYes — rest of line is prose
12INPUTTest I/ONo
13EXPECTTest I/ONo
14NOTTest operatorNo
15CONTAINSTest operatorNo
16MATCHESTest operatorNo

These look like they could be keywords but are not:

  • true / false — boolean literals, not keywords
  • Identifiers after AGENT, CONSTRAINTS, FLOW — user-defined names
  • File paths after SYSTEM, IMPORT — path literals
  • Quoted strings — string literals