Scope environment variables per component
Build two components that both read the same environment variable name but can be given different values - one per component - without touching the global variable. You will also see the .env file kdeps scaffolds for each component on first run.
When a component runs, env('API_KEY') is resolved in this order:
{COMPONENT_NAME_UPPER}_API_KEYin the process environment (scoped override)- Plain
API_KEYin the process environment API_KEYin the component's own.envfile (lowest priority)
So a translator component and a summarizer component can each get their own key while sharing one variable name in the YAML.
Step 1: create the structure
mkdir -p envdemo/components/translator
mkdir -p envdemo/components/summarizer
mkdir envdemo/resources
cd envdemoStep 2: two components that read the same variable
Create components/translator/component.yaml:
# components/translator/component.yaml
apiVersion: kdeps.io/v1
kind: Component
metadata:
name: translator
version: "1.0.0"
interface:
inputs:
- name: text
type: string
required: true
resources:
- actionId: translate
name: Translate
exec:
command: "echo"
args:
- "translator using key: {{ env('API_KEY', 'none') }} -- text: {{ input('text') }}"
apiResponse:
success: true
response:
out: "{{ trim(get('translate').stdout) }}" # the echoed line, not the whole exec resultCreate components/summarizer/component.yaml, the same shape under its own name:
# components/summarizer/component.yaml
apiVersion: kdeps.io/v1
kind: Component
metadata:
name: summarizer
version: "1.0.0"
interface:
inputs:
- name: text
type: string
required: true
resources:
- actionId: summarize
name: Summarize
exec:
command: "echo"
args:
- "summarizer using key: {{ env('API_KEY', 'none') }} -- text: {{ input('text') }}"
apiResponse:
success: true
response:
out: "{{ trim(get('summarize').stdout) }}" # the echoed line, not the whole exec resultStep 3: call both components
Create resources/01-translate.yaml:
# resources/01-translate.yaml
actionId: runTranslate
name: Run translator
component:
name: translator
with:
text: "hello"Create resources/02-summarize.yaml:
# resources/02-summarize.yaml
actionId: runSummarize
name: Run summarizer
component:
name: summarizer
with:
text: "a long paragraph"Create resources/03-response.yaml:
# resources/03-response.yaml
actionId: response
name: Response
requires: [runTranslate, runSummarize]
apiResponse:
success: true
response:
translator: "{{ output('runTranslate').data.out }}" # a component call returns its apiResponse
summarizer: "{{ output('runSummarize').data.out }}"Step 4: add the route
Create workflow.yaml:
# workflow.yaml
apiVersion: kdeps.io/v1
kind: Workflow
metadata:
name: envdemo
version: "1.0.0"
targetActionId: response
settings:
apiServer:
portNum: 16395
routes:
- path: /run
methods: [GET]Step 5: run with scoped keys
kdeps validate .
export KDEPS_API_AUTH_TOKEN=dev-token
# Shared default for both components
export API_KEY=global-key
# Override just the translator
export TRANSLATOR_API_KEY=translate-key
kdeps run .curl "http://localhost:16395/run" -H "Authorization: Bearer $KDEPS_API_AUTH_TOKEN"Response:
{
"success": true,
"data": {
"translator": "translator using key: translate-key -- text: hello",
"summarizer": "summarizer using key: global-key -- text: a long paragraph"
}
}The translator saw TRANSLATOR_API_KEY; the summarizer fell back to API_KEY.
Step 6: inspect the scaffolded files
On the first run kdeps created these (it never overwrites existing ones):
cat components/translator/.env # template listing every env() var, blank
cat components/translator/README.md # generated from component.yaml metadataFill in .env to provide a lowest-priority fallback value when no process environment variable is set.
Next steps
- Components reference - env derivation,
.envdetails - Reusable component tutorial - building a component
- Global config - named connections with shared credentials
- Jinja2 templates -
env()in YAML preprocessing
