agentsclimarketplace

Kora config yaml

Skill kora-projects/kora-skills/plugins/kora-v1/skills/kora-config-yaml

Agent Skills for Kora Framework — compile-time DI for Java/Kotlin backend development.

Install
npx -y skills add kora-projects/kora-skills --skill kora-config-yaml

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

YAML configuration for Kora applications via the config-yaml artifact and YamlConfigModule. Binds application.yaml sections to type-safe interfaces with @ConfigSource and reusable shapes with @ConfigValueExtractor. Covers environment-variable substitution (${VAR}, ${?VAR}, ${VAR:default}), self-references, @Nullable optional values, default method bodies, and selecting files with config.resource/config.file. Use when a Kora service must read configuration from YAML instead of HOCON, when wiring @ConfigSource/@ConfigValueExtractor over an application.yaml, or when debugging unresolved YAML substitutions at startup.

SKILL.md

9.4 KB, as published. Nobody here has run it

Kora Config YAML

YAML configuration for Kora, parsed by SnakeYAML and bound to type-safe Java/Kotlin interfaces. HOCON is the recommended default for new Kora projects; use YAML when a project requires it. The binding API (@ConfigSource, @ConfigValueExtractor, @Nullable, default methods, env substitution) is identical for both formats — only the file syntax differs.

Quick Start

1. Dependency (build.gradle)

All Kora artifacts inherit their version from the kora-parent BOM; never pin a version on an individual ru.tinkoff.kora:* dependency. The annotation processor is mandatory — @ConfigSource generates a *ConfigValueExtractor at compile time and nothing is bound without it.

dependencies {
    koraBom platform("ru.tinkoff.kora:kora-parent:1.2.17")
    annotationProcessor "ru.tinkoff.kora:annotation-processors"

    implementation "ru.tinkoff.kora:config-yaml"
    implementation "ru.tinkoff.kora:logging-logback"
}

Kotlin uses KSP instead: ksp "ru.tinkoff.kora:symbol-processors".

2. Enable the module

import ru.tinkoff.kora.application.graph.KoraApplication;
import ru.tinkoff.kora.common.KoraApp;
import ru.tinkoff.kora.config.yaml.YamlConfigModule;
import ru.tinkoff.kora.logging.logback.LogbackModule;

@KoraApp
public interface Application extends YamlConfigModule, LogbackModule {

    static void main(String[] args) {
        KoraApplication.run(ApplicationGraph::graph);
    }
}

3. Config file (src/main/resources/application.yaml)

app:
    name: ${APP_NAME:Task Management App}   # default if APP_NAME unset
    version: ${APP_VERSION}                  # required, fails fast if missing
    environment: "development"

4. Typed interface

@ConfigSource("app") registers the bound AppConfig as a graph component that any constructor can request.

import ru.tinkoff.kora.config.common.annotation.ConfigSource;

@ConfigSource("app")
public interface AppConfig {

    String name();

    String version();

    String environment();
}

5. Inject it

Configuration is a normal graph dependency — request it via the constructor.

import ru.tinkoff.kora.common.Component;

@Component
public final class GreetingService {

    private final AppConfig config;

    public GreetingService(AppConfig config) {
        this.config = config;
    }
}

What's in this skill

FilePurpose
references/yaml-config-reference.mdYAML syntax, supported value types, substitution rules, file resolution, optional/default values, troubleshooting
assets/README.mdCopy-paste application.yaml and @ConfigSource interface templates

When to use vs not

Use YAML config whenUse HOCON (kora-config-hocon) instead when
The project mandates YAMLStarting a new Kora service with no format constraint
Existing application.yaml files must be keptYou want string concatenation and the richer HOCON merge model

Both formats use the same @ConfigSource/@ConfigValueExtractor API; switching is a dependency swap (config-yamlconfig-hocon) plus the module interface.

Core patterns

Two binding styles

AnnotationUse forBehavior
@ConfigSource("path")One fixed section bound to a graph componentAuto-registers a component for that exact path
@ConfigValueExtractorA reusable shape extracted from several pathsGenerates an extractor; you call extractor.extract(config.get("...")) in a factory

Environment-variable substitution

Three forms, all resolved by Kora before binding:

foo:
    valueRequired: ${ENV_VALUE_REQUIRED}            # required — startup fails if unset
    valueOptional: ${?ENV_VALUE_OPTIONAL}           # optional — key is omitted if unset
    valueDefault: ${ENV_VALUE_DEFAULT:someDefault}  # default literal used if unset
    valueRef: ${foo.valueRequired}-suffix           # reference another config value

${?VAR} requires a @Nullable return type because the value may be absent.

Optional and default values (no @DefaultValue annotation exists)

Kora has no defaulting annotation. Express optional and default values in code:

import jakarta.annotation.Nullable;

@ConfigSource("app")
public interface AppConfig {

    String name();                 // required

    @Nullable
    String description();          // optional — null when missing (use with ${?VAR})

    default int retries() {        // default value via method body
        return 3;
    }
}

Any @Nullable (jakarta, javax, JetBrains) works. In Kotlin, mark the return type nullable (fun description(): String?) and use a default method body for defaults.

Nested objects via @ConfigValueExtractor

Nested config types are NOT nested @ConfigSource interfaces — the inner shape is annotated @ConfigValueExtractor and exposed as a method on the parent:

import ru.tinkoff.kora.config.common.annotation.ConfigSource;
import ru.tinkoff.kora.config.common.annotation.ConfigValueExtractor;
import java.time.Duration;

@ConfigSource("app")
public interface AppConfig {

    String name();

    PoolConfig pool();   // nested object

    @ConfigValueExtractor
    interface PoolConfig {

        int maxSize();

        Duration connectionTimeout();
    }
}
app:
    name: "my-service"
    pool:
        maxSize: 20
        connectionTimeout: "30s"   # Duration parses ISO-like strings

Reusing one shape under multiple paths

When the same shape appears more than once (e.g. two clients), bind it with @ConfigValueExtractor and produce tagged instances from factory methods on the @KoraApp interface. See references/yaml-config-reference.md for the full @Tag + ConfigValueExtractor.extract(config.get(...)) pattern.

Supported value types

Kora binds YAML to String, primitives and boxed numbers, BigInteger, BigDecimal, boolean, UUID, Pattern, enums, LocalDate/LocalTime/ LocalDateTime/OffsetTime/OffsetDateTime, Duration, Period, List/Set/Map<String,?>, Properties, and nested @ConfigValueExtractor types (including lists of them). Full table in the reference.

Selecting the config file

Kora merges all reference.yaml files (library defaults), then overlays the application file. The application file is resolved in priority order:

  1. config.resource system property — a file on the classpath (resources/)
  2. config.file system property — a file on the filesystem
  3. application.yaml on the classpath
  4. an empty config if none of the above exists

There is no config.environment profile mechanism. For per-environment files, create a complete alternative such as application-prod.yaml and select it explicitly:

./gradlew run -Dconfig.resource=application-prod.yaml

The alternative file must be self-contained (it replaces, not layers over, application.yaml).

Common pitfalls

SymptomCause / fix
Startup fails: unresolved substitutionA ${VAR} (required form) has no value. Provide the env var/system property, or switch to ${VAR:default} / ${?VAR}
@DefaultValue does not compileThat annotation does not exist in Kora — use a default method body
Nested @ConfigSource with relative path does nothingNested types use @ConfigValueExtractor, not a second @ConfigSource
YAML parse errorYAML is indentation-sensitive; use spaces only (no tabs), and quote values containing : or #
Optional value throws on missing keyAdd @Nullable to the method (Kotlin: nullable return) and pair with ${?VAR}
Config component "not found" in the graphAnnotation processor missing, or @KoraApp does not extend YamlConfigModule
Both config-yaml and config-hocon on the classpathUse exactly one config format module

Related skills

Source of truth

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.