Install
$ agentstack add skill-dungnotnull-urban-noise-tree-barrier-planning-agent-skill-urban-noise-tree-barrier-planning-agent-skill ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
SKILL.md — Skill Registry
urban-noise-tree-barrier-planning is built on a modular skill-registry pattern. This document is the canonical reference for how skills are registered, resolved, executed, and validated, including the input/output JSON Schemas, the tool layer, the lifecycle hooks, and the chain-of-thought router.
The registry is implemented in src/urban_noise_barrier/registry.py (SkillRegistry, SkillSpec, SkillResult) and orchestrated by src/urban_noise_barrier/engine.py (Engine).
1. Concepts
| Concept | Class | File | Purpose | |---------|-------|------|---------| | Skill | SkillSpec | registry.py | A unit of work: name, stage, handler, schemas, gates, fallback | | Skill registry | SkillRegistry | registry.py | Register / resolve / execute / validate skills | | Tool | Tool | tools/__init__.py | A deterministic function with JSON Schema I/O | | Tool registry | ToolRegistry | tools/__init__.py | Register / invoke tools | | Hook bus | HookBus | hooks.py | Lifecycle event publish/subscribe | | Router | Router | router.py | CoT intent → ordered skill list | | Context | ContextManager | context.py | Token-budgeted artifact store | | Config | Config | config.py | Layered type-safe configuration | | Engine | Engine | engine.py | Wires everything + runs the pipeline |
2. Register
A skill is registered as a SkillSpec dataclass:
SkillSpec(
name="sub-core-analysis", # unique, matches skills/*.md frontmatter
description="Noise map, barrier, species, vegetation, co-benefits, scenarios.",
stage="analysis", # intake|evidence|analysis|knowledge|synthesis|gate|routing
handler=_handler_core_analysis, # callable(inputs: dict, ctx: Engine) -> dict
inputs_schema={"type": "object"}, # JSON Schema (optional)
outputs_schema=CoreAnalysis.json_schema, # JSON Schema (optional)
gates=["G1", "G2", "G3", "G4"], # quality-gate ids this skill satisfies
fallback=_fallback_core_analysis, # optional recovery handler
markdown_path="skills/sub-core-analysis.md",
retry_max=2,
tags=["core"],
)
SkillRegistry.register(spec) validates the spec (non-empty name, callable handler with (inputs, ctx) signature, dict schemas) and refuses duplicates.
Registered skills (default pipeline):
| name | stage | gates | fallback | |------|-------|-------|----------| | sub-router | routing | — | — (deterministic) | | sub-gather-requirements | intake | U4 | — | | sub-evidence-collector | evidence | U1, U3 | empty degraded bundle (level 3) | | sub-core-analysis | analysis | G1–G4 | — | | sub-knowledge-updater | knowledge | U1 | Weak-coverage empty result | | sub-advisor | synthesis | U2, U6 | — | | sub-quality-gate | gate | U5 | — |
3. Resolve
Resolution is name-based and stage-aware:
registry.get(name)→SkillSpec(raisesSkillErrorif missing).registry.by_stage(stage)→ all skills in a stage (registration order).registry.names()→ ordered list of registered skill names.
The router (Router.route) resolves a request into an ordered skill list (Route.skills). The engine executes Route.skills in order, so the router is the single source of truth for "which skills run".
4. Execute
SkillRegistry.execute(name, inputs, ctx):
- emit
skill.prehook. - validate inputs against
inputs_schema(JSON Schema viajsonschema
if installed, else the built-in subset validator).
- call
handler(inputs, ctx)with retry (up toretry_max); recoverable
SkillErrors retry, non-recoverable ones propagate.
- on exhaustion, fall back to
spec.fallbackif present. - validate outputs against
outputs_schema. - emit
skill.posthook. - return a
SkillResult(outputs, degradationlevel, usedfallback, retries,
gates_passed, notes, error).
The Engine.run(request, analysis_inputs) wires this together: route → execute each skill in order → thread outputs through ContextManager → run sub-quality-gate → assemble AnalysisReport.
5. Validate
Validation happens at four layers:
- Spec validation — at registration (
SkillSpec.validate_spec). - Schema validation — inputs + outputs against JSON Schema. Canonical
schemas are exported to assets/schemas/*.json via scripts/export_schemas.py.
- Gate validation —
sub-quality-gateruns U1–U6 + G1–G4 against the
assembled report and returns {gates, all_passed, failed, strict}.
- Project validation —
scripts/validate_project.pychecks the file
contract, frontmatter, runtime construction, config, and knowledge brain.
Input/Output JSON Schemas (canonical)
Schemas are defined as class attributes on the models in src/urban_noise_barrier/schemas.py and exported to assets/schemas/.
Example — Requirements (input/output of sub-gather-requirements):
{
"type": "object",
"required": ["object"],
"properties": {
"object": {"type": "string", "minLength": 1},
"scope": {"type": "string"},
"timeframe": {"type": "string"},
"available_inputs": {"type": "array", "items": {"type": "string"}},
"target_audience": {"type": "string"},
"language": {"type": "string", "enum": ["en", "vi"]},
"analysis_type": {"type": "string"}
}
}
Example — AdvisorConclusion (output of sub-advisor):
{
"type": "object",
"required": ["verdict", "scenarios", "key_risks", "evidence_chain", "remediation", "disclosure"],
"properties": {
"verdict": {"type": "string", "enum": ["Effective Barrier Plan",
"Conditional (species)", "Insufficient Attenuation", "Inconclusive"]},
"scenarios": {"type": "object"},
"key_risks": {"type": "array", "minItems": 1},
"evidence_chain": {"type": "array"},
"remediation": {"type": "array"},
"disclosure": {"type": "string", "minLength": 1}
}
}
Full set: Requirements, EvidenceBundle, NoiseMap, BarrierDesign, SpeciesSelection, VegetationAttenuation, CoBenefits, CoreAnalysis, KnowledgeEvidence, AdvisorConclusion, AnalysisReport.
6. Tools
Tools are the deterministic computation layer invoked by skill handlers.
| Tool name | Input schema (key fields) | Output schema (key fields) | Method | |-----------|---------------------------|----------------------------|--------| | acoustics.noise_map | speedkmh, vehicleflowperh, receptors[], barrier? | sourceleveldb, receptors[] (receivedleveldb), barrier (insertionlossdb) | CNOSSOS subset + Maekawa | | vegetation.attenuation | beltwidthm, canopydensity, dbper30m? | attenuationdb, method | empirical saturation curve | | species.select | site{hardinesszone, minheightm, tolerances…}, topk | candidates[], selected[] (with score+rationale) | weighted tolerance + zone match | | airquality.cobenefits | beltaream2, treecount, lai? | pmdepositionkgperyear, co2sequestrationkgperyear, coolingkwhsavedperyear | i-Tree-style deposition | | evidence.collect | currentdata[], authoritativedocs[], … | normalized buckets, degradationlevel, limitationflag | tier assignment + gate | | knowledge.query | keywords[], topk? | citations[] (tier+relevance), gaps[], coverage | brain parse + score |
Tools are registered via default_tool_registry() and invoked through ToolRegistry.invoke(name, inputs, ctx). Each tool validates its own I/O against JSON Schema.
7. Hooks
The HookBus (src/urban_noise_barrier/hooks.py) emits lifecycle events:
| Event | When | |-------|------| | engine.start / engine.end | engine run boundaries | | skill.pre / skill.post / skill.error | per-skill lifecycle | | tool.pre / tool.post / tool.error | per-tool lifecycle | | gate.pre / gate.post / gate.failed | quality-gate lifecycle | | degradation | degradation level raised | | context.compaction | context manager compacted artifacts | | knowledge.append | brain entry appended | | state.sync | state snapshot requested |
Built-in hooks: logging_hook (structured log per event), metrics_hook (per-event counters), state_sync_hook (snapshot persistence). Custom hooks register via bus.register(event, callback).
8. Router (chain-of-thought)
Router.route(request, requirements) returns a Route:
{
"intent": "full_analysis",
"skills": ["sub-gather-requirements", "sub-evidence-collector",
"sub-core-analysis", "sub-knowledge-updater",
"sub-advisor", "sub-quality-gate"],
"flags": {"require_scenarios": true},
"reasoning": [{"step": "intent-classification", "observation": "...", "decision": "..."}],
"degradation_level": 0
}
Routing is deterministic and fully testable. The LLM-facing CoT prompt (router_cot) is in references/prompt_templates.md.
9. Extending the Registry
To add a new skill:
- Write
skills/sub-.mdwith frontmattername+descriptionand the
required sections (Role & Persona, Workflow, Tools, Output Format, Quality Gates).
- Implement a handler
(inputs, ctx) -> dictinengine.py. - Register a
SkillSpecinEngine._register_skills. - Add the skill to the router pipeline(s) if it should be routable.
- Export/generate any new JSON Schemas via
scripts/export_schemas.py. - Add a test under
tests/.
To add a new tool:
- Subclass
Toolinsrc/urban_noise_barrier/tools/.py, set class
attributes name, description, input_schema, output_schema, and implement execute.
- Register it in
default_tool_registry(). - Add a test under
tests/.
10. File map
skills/main.md # orchestrator + router + gates (this contract)
skills/sub-*.md # one markdown doc per registered skill
src/urban_noise_barrier/ # Python implementation
engine.py registry.py router.py hooks.py config.py
context.py schemas.py errors.py logging_setup.py cli.py
tools/{acoustics,vegetation,species,air_quality,evidence,knowledge}.py
assets/schemas/*.json # canonical JSON Schemas (exported)
config/default.yaml # layered configuration
references/ # domain methods, prompts, species DB, sources
scripts/ # setup, seed, ingest, run, validate, export
tests/ # pytest unit + scenario tests
SECOND-KNOWLEDGE-BRAIN.md # living knowledge base
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: dungnotnull
- Source: dungnotnull/urban-noise-tree-barrier-planning-agent-skill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.