Generic Action Nodes
issue.* / llm.* / text action nodes.
Generic action nodes provide tracker-agnostic issue operations, direct LLM inference, and text utilities. These nodes are designed for portability: issue.* nodes route through your project's active tracker binding (Linear, GitHub Issues, Jira, or Asana) without requiring tracker-specific configuration on the node itself.
Issue nodes (tracker-agnostic)
The issue.* family projects operations onto a canonical issue shape and routes to whichever tracker is configured as the project's primary tracker. This makes workflows portable across organizations using different trackers.
issue.read
Reads an issue from the project tracker and returns it in the canonical cross-provider shape.
Input ports
| Port | Type | Required | Description |
|---|---|---|---|
issueId | string | yes | Tracker-native issue ID or identifier. Linear: UUID or identifier (e.g. REN-1234). GitHub Issues: owner/repo#42. Jira: PROJ-1. Asana: GID. |
trackerOverride | string | no | Pin to a specific tracker. A numeric ID selects an exact tracker; a provider name (e.g. linear) selects the first active tracker of that provider on the project. Omit to use the project primary tracker. |
Output ports
| Port | Type | Description |
|---|---|---|
output | IssueReadResult | Issue in canonical shape, or an error reason |
IssueReadResult shape
{
ok: boolean
issue?: {
id: string
identifier: string // e.g. "REN-1234" or "#42"
title: string
description?: string
status: string
url: string
labels?: string[]
assigneeId?: string
provider: string // "linear" | "github_issues" | "jira" | "asana"
}
details?: object // Raw provider response for debugging
reason?: string // Error message when ok=false
}issue.update_status
Updates the status of an issue using its canonical tracker state name. The node handles the translation from the canonical name to the tracker-native state identifier.
Input ports
| Port | Type | Required | Description |
|---|---|---|---|
issueId | string | yes | Tracker-native issue ID |
status | string | yes | New status name (uses tracker-canonical names, e.g. "Started" for Linear, "open" / "closed" for GitHub Issues) |
trackerOverride | string | no | Pin to a specific tracker |
Output ports - success ({ updated: boolean }) / fail ({ error: string })
issue.add_comment
Adds a comment to an issue on the project's active tracker.
Input ports
| Port | Type | Required | Description |
|---|---|---|---|
issueId | string | yes | Tracker-native issue ID |
body | string | yes | Comment body (Markdown supported on most trackers) |
trackerOverride | string | no | Pin to a specific tracker |
Output ports - success ({ id: string }) / fail ({ error: string })
LLM nodes
The llm.* pair separates configuration from execution. Declare a shared llm.config node and wire it to one or more llm.inference nodes - this lets you swap models or adjust parameters in one place rather than on every inference node.
llm.config
Declares a reusable LLM configuration as a first-class graph node. Its output port carries an LlmConfig object consumed by downstream llm.inference nodes.
Config schema
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
model | string | yes | - | Model identifier. Examples: claude-opus-4-8, gpt-5.4, gemini-2.5-pro, anthropic/claude-3.5-sonnet |
provider | string | no | openrouter | claude (Anthropic), codex (OpenAI), gemini (Google), openrouter (OpenRouter gateway) |
temperature | number | no | 0.2 | Sampling temperature, 0.0-2.0 |
maxTokens | number | no | 1024 | Maximum output tokens per call, 1-128,000 |
systemPrompt | string | no | - | System prompt prepended to every inference call using this config |
credentialId | string | no | - | Optional credential override; uses org-default credential when omitted |
Output port - output (LlmConfig): the configuration object, ready to wire to llm.inference.
llm.inference
Calls an LLM and returns the generated text (and optionally parsed JSON). Accepts either a prompt string shortcut or a full messages array, plus optional overrides for model, temperature, max tokens, and system prompt.
Input ports
| Port | Type | Required | Description |
|---|---|---|---|
config | LlmConfig | no | Configuration from an upstream llm.config node |
prompt | string | no | Single user message shortcut. Mutually exclusive with messages in config. |
Config schema (inline fields, supplement or override config)
| Field | Type | Description |
|---|---|---|
prompt | string | Single user message. Mutually exclusive with messages. |
messages | Array<{ role, content }> | Full chat history. Roles: system, user, assistant. |
jsonMode | boolean | Ask the model to return JSON. Parsed object appears on output.json. |
model | string | Override config.model |
temperature | number | Override config.temperature |
maxTokens | number | Override config.maxTokens |
systemPrompt | string | Override config.systemPrompt |
Output port - output (InferenceResult)
InferenceResult shape
{
text: string // Generated text
json?: object // Parsed JSON when jsonMode=true
finishReason?: string // "stop", "length", "tool_calls", etc.
usage?: {
promptTokens: number
completionTokens: number
totalTokens: number
}
model?: string // Actual model used
latencyMs?: number // End-to-end latency
}Example: classify an issue
steps:
- id: llm_cfg
type: action
nodeId: llm.config
config:
provider: claude
model: claude-opus-4-8
temperature: 0
maxTokens: 256
systemPrompt: "Classify the following issue as bug, feature, or chore. Respond with JSON."
- id: classify
type: action
nodeId: llm.inference
config:
prompt: "{{ nodes.readIssue.output.issue.title }}: {{ nodes.readIssue.output.issue.description }}"
jsonMode: true
- id: check_class
type: condition
nodeId: rensei.value.switch
config:
value: "{{ nodes.classify.output.json.classification }}"
cases:
- bug
- feature
- choreText utility
rensei.text.keyword_prefix
Prepends a keyword prefix to a string value. Used in the SDLC templates to stamp work-type labels (e.g. "Research: ", "Backlog: ") onto comment bodies or issue titles before passing them downstream.
Input ports
| Port | Type | Required | Description |
|---|---|---|---|
text | string | yes | Input text |
prefix | string | yes | Prefix to prepend |
Output port - output ({ text: string }): "${prefix}${text}"
When to use issue.* vs provider-specific nodes
| Scenario | Recommended approach |
|---|---|
| Workflow serves a single org with a known tracker | Use provider-specific nodes (linear.*, github_issues.*) for the richer field set and more control |
| Workflow template shipped to multiple orgs with different trackers | Use issue.* nodes for portability |
| SDLC template that should work with both Linear and GitHub Issues | Use issue.* - the SDLC v2 template uses this pattern |
Related pages
- Linear Action Nodes - full Linear issue lifecycle
- GitHub Issues Action Nodes - full GitHub Issues lifecycle
- Condition Nodes -
rensei.agent_result.switch,rensei.value.switch - Foundational Nodes -
llm-model- project an LLM profile ref ontollm.config