Jobs are typed, executable units of work with strict input/output schemas, automatic retries, timeouts, permission checks, and background execution support. They are designed for operations that need reliability guarantees beyond what a simple tool call provides.Documentation Index
Fetch the complete documentation index at: https://docs.agentfront.dev/llms.txt
Use this file to discover all available pages before exploring further.
Jobs extend the FrontMCP execution model with persistent state tracking, retry logic, and DAG-based composition via Workflows.
Why Jobs?
Jobs fill the gap between lightweight tool calls and full workflow orchestration:| Aspect | Tool | Job | Workflow |
|---|---|---|---|
| Purpose | Execute a single action | Execute a reliable unit of work | Orchestrate multiple jobs |
| Retries | None | Automatic with exponential backoff | Per-step retry overrides |
| Background | No | Yes (with runId polling) | Yes (with runId polling) |
| State tracking | None | pending / running / completed / failed | Per-step state tracking |
| Timeout | None | Configurable (default: 5 min) | Configurable (default: 10 min) |
| Permissions | Auth providers | RBAC with roles, scopes, custom guards | Inherits from job permissions |
- Data processing — ETL pipelines, file parsing, batch operations
- External integrations — API calls that may fail and need retries
- Long-running operations — background tasks with progress reporting
- Auditable actions — operations that need execution logs and state tracking
Creating Jobs
Class Style
Use class decorators for jobs that need dependency injection, lifecycle hooks, or complex logic:Function Style
For simpler jobs, use the functional builder:Registering Jobs
Add jobs to your app via thejobs array:
Loading from npm or Remote Servers
Mix local jobs with those loaded from npm or proxied from remote servers:Job.esm() and Job.remote() load individual jobs. For loading entire apps, use App.esm() or App.remote().jobsConfig:
Input & Output Schemas
Jobs require both input and output schemas using Zod:Configuration
| Field | Type | Default | Description |
|---|---|---|---|
name | string | — | Required. Unique job identifier |
description | string | — | Human-readable description |
inputSchema | ZodShape | — | Required. Zod schema for input validation |
outputSchema | ZodShape | — | Required. Zod schema for output validation |
id | string | name | Stable identifier for tracking |
timeout | number | 300000 | Maximum execution time in ms (5 min) |
retry | JobRetryConfig | — | Retry configuration (see below) |
tags | string[] | — | Categorization tags |
labels | Record<string, string> | — | Fine-grained key-value labels |
hideFromDiscovery | boolean | false | Hide from list-jobs |
permissions | JobPermission[] | — | RBAC permission rules |
Retry Configuration
Jobs support automatic retries with exponential backoff:| Field | Type | Default | Description |
|---|---|---|---|
maxAttempts | number | 3 | Maximum retry attempts |
backoffMs | number | 1000 | Initial backoff delay in ms |
backoffMultiplier | number | 2 | Backoff multiplier per attempt |
maxBackoffMs | number | 60000 | Maximum backoff delay in ms |
maxBackoffMs).
Permissions
Jobs support RBAC-style permission checks:| Field | Type | Description |
|---|---|---|
action | 'create' | 'read' | 'update' | 'delete' | 'execute' | 'list' | Permission action type |
roles | string[] | Required roles (at least one must match) |
scopes | string[] | Required OAuth scopes (at least one must match) |
custom | (authInfo) => boolean | Promise<boolean> | Custom guard function |
Background Execution
Jobs can run in background mode, returning arunId for status polling:
Via DirectClient
Progress Reporting
Jobs can report progress and log messages during execution:| Method | Signature | Description |
|---|---|---|
this.log(message) | log(message: string): void | Append a timestamped log entry |
this.progress(pct, total?, msg?) | progress(pct: number, total?: number, msg?: string): Promise<boolean> | Send progress notification to client |
this.getLogs() | getLogs(): readonly string[] | Retrieve all log entries |
this.attempt | get attempt(): number | Current retry attempt (1-based) |
Job Stores
Jobs use two stores for persistence:State Store
Tracks execution state (JobRunRecord): run ID, state, input, result, error, logs, timing.
Definition Store
Persists dynamic job definitions registered at runtime via theregister-job tool.
Memory (Default)
Suitable for development. Data is lost on restart.Redis
For production, configure Redis storage:MCP Tools
When jobs are enabled, the following MCP tools are automatically registered:| Tool | Description |
|---|---|
list-jobs | List registered jobs with optional tag/label filtering |
execute-job | Execute a job (inline or background) |
get-job-status | Get execution status by runId |
register-job | Register a dynamic job at runtime |
remove-job | Remove a dynamic job |
Best Practices
Do:- Define clear input and output schemas with
.describe()on each field - Use retries for operations that call external services
- Set appropriate timeouts based on expected execution time
- Use background mode for long-running operations
- Log meaningful progress messages for debugging
- Use jobs for simple, synchronous operations (use tools instead)
- Set
maxAttemptstoo high for non-idempotent operations - Skip output schemas — they enable validation and type safety
- Forget to handle the retry
attemptnumber in your logic
Next Steps
Workflows
Compose jobs into multi-step pipelines
JobContext
Context class API reference
@Job
Decorator reference
JobRegistry
Registry API reference