ANGULAR DYNAMIC FORMS

What is dynamic forms in angular ?– The most asked interview question

In simple terms, dynamic forms mean that the form field configuration comes from the backend as a JSON response. On the frontend, we simply read this configuration and render the form dynamically with minimal code.
Lets see how we can achieve this

First let me clarify Reactive forms include static form field declaration which means you will need to declare each field and use the same in fromGroup but here as the fields come from JSON you just need to dynamically handle the fields in formGroup.

.ts file

`export class DynamicFormComponent implements OnInit {

  form!: FormGroup;
//json from BE
  fields = [
    { type: 'text', name: 'firstName', label: 'First Name', required: true },
    { type: 'email', name: 'email', label: 'Email', required: true },
    { type: 'number', name: 'age', label: 'Age', required: false }
  ];

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    const group: any = {};

    this.fields.forEach(field => {
      group[field.name] = field.required
        ? ['', Validators.required]
        : [''];
    });

    this.form = this.fb.group(group);
  }`

.html file

`  <div *ngFor="let field of fields">
    <label>{{ field.label }}</label>

    <input
      [type]="field.type"
      [formControlName]="field.name"
    />

    <div *ngIf="form.get(field.name)?.invalid && form.get(field.name)?.touched">
      {{ field.label }} is required
    </div>
  </div>

`

Building AI Agents: A 3-Level Roadmap for Developers

In 2026, a developer I know spent three weeks reading papers on transformer architectures before writing a single line of agent code. He never shipped anything. Meanwhile, a colleague with no machine learning background built a working document-retrieval agent in four days using n8n, a vector store, and a few well-structured prompts. The difference was not intelligence or experience. It was knowing where to start.

According to McKinsey’s State of AI in 2024, 72% of organizations now use AI in at least one business function, up from 50% in previous years. That adoption gap is closing fast, and the developers who will fill it are not ML researchers. They are engineers who understand how to connect systems, write clear instructions, and debug pipelines. If you are one of those engineers, this roadmap is for you.

The three stages below are not arbitrary. Each one builds a specific capability that the next stage depends on. Skip a stage and you will hit a wall that feels like a knowledge problem but is actually a sequencing problem.

Stage 1: Retrieval-Augmented Generation as Your Foundation

Most developers approach their first agent by asking: “Which model should I use?” That is the wrong first question. The right question is: “What does the agent need to know, and where does that knowledge live?”

Retrieval-Augmented Generation, or RAG, answers that question structurally. Instead of fine-tuning an LLM on your data (expensive, slow, brittle), you store your knowledge in a vector database and retrieve relevant chunks at query time. The reasoning engine sees the retrieved context alongside the user’s question and generates a grounded response.

Here is what a minimal RAG pipeline actually requires:

  • A document ingestion step that chunks your source material and embeds each chunk into a vector store (Pinecone, Qdrant, and Weaviate are the common choices in 2026)
  • A retrieval step that embeds the incoming query and runs a similarity search against the store
  • A generation step where an LLM receives the retrieved chunks as context and produces an answer

The most common Stage 1 failure is chunk sizing. Chunks that are too large dilute relevance; chunks that are too small lose context. Start with 512-token chunks and 50-token overlaps, then adjust based on retrieval quality. You will know retrieval is failing when the agent confidently answers questions using the wrong source document.

This stage is where most developers underestimate prompt engineering. The system prompt that wraps your retrieved context is not boilerplate. It controls whether the agent cites its sources, refuses out-of-scope questions, or hallucinates when retrieval returns nothing useful. Write it deliberately. Test it against adversarial inputs before you build anything on top of it.

Stage 2: Parameter Tuning and Behavioral Control

Once your RAG pipeline returns accurate answers, the next problem is consistency. An agent that gives correct answers 80% of the time and confident wrong answers 20% of the time is not useful in production. Stage 2 is about closing that gap through parameter tuning and structured behavioral constraints.

Temperature is the parameter developers adjust first, usually by guessing. A better approach: run your evaluation set at temperature 0, 0.3, 0.7, and 1.0, then measure answer consistency and factual accuracy across runs. For retrieval-grounded tasks, lower temperatures almost always outperform higher ones. For creative or generative tasks, the relationship inverts. Know which task type you are building for before you pick a number.

Prompt engineering at this stage goes beyond system prompts. You are now writing few-shot examples, output format constraints, and chain-of-thought scaffolding. The practical test for a well-engineered prompt: can a new developer read it and predict what the agent will do? If the answer is no, the prompt is doing too much implicit work and will break when inputs change.

One pattern worth adopting early: separate your behavioral instructions from your context injection. Keep the system prompt focused on how the agent should reason and respond. Keep the retrieved context in the human turn or a dedicated context block. Mixing them creates prompts that are hard to debug and harder to update.

This is also where I learned a painful lesson about build scripts. We ran a workflow update script that was supposed to modify 4 nodes in a pipeline. Instead, it added 12 duplicate nodes. The script searched for node names that had already been renamed by the previous run, found nothing, and appended fresh copies without checking whether they already existed. The pipeline went from 32 nodes to 44. Every build script we write now is idempotent: it removes existing nodes by name before adding fresh ones, handles both pre- and post-rename node names, and verifies the final node count matches the expected total. The same discipline applies to prompt versioning. If you are not tracking prompt changes with the same rigor as code changes, you will spend hours debugging a regression that was actually a prompt edit from two weeks ago.

Stage 3: Multi-Agent Orchestration

Single agents hit a ceiling. They work well for focused tasks with clear inputs and outputs. They struggle with tasks that require parallel reasoning, specialized sub-skills, or long-horizon planning. That is where multi-agent architectures come in.

The core pattern is a coordinator-worker structure. A routing component receives the incoming task, classifies it, and dispatches it to a specialized worker. Each worker handles a narrow domain: one for document retrieval, one for calculation, one for external API calls. The coordinator aggregates results and formats the final response.

What ForgeWorkflows calls a “modular swarm” is this pattern taken to its logical conclusion: each worker is independently testable, independently replaceable, and communicates through a shared message schema rather than direct coupling. You can swap out the retrieval worker without touching the calculation worker. That independence is what makes the system maintainable as it grows.

The honest tradeoff here is latency. A single agent that handles everything in one pass will almost always respond faster than a coordinator routing to three specialized workers. If your use case requires sub-second responses, multi-agent orchestration is probably the wrong architecture. If your use case requires accuracy across heterogeneous tasks, the latency cost is usually worth paying.

Debugging multi-agent systems is also genuinely harder. When a single agent fails, you have one prompt and one output to inspect. When a coordinator-worker chain fails, the error could originate at any node in the chain, and the coordinator’s output may look plausible even when a worker upstream produced garbage. Build logging into every worker from day one. Log the input, the retrieved context, the raw model output, and the parsed result. Without that, you are debugging blind.

For developers building these pipelines in n8n, the practical advice is to treat each worker as a sub-workflow with its own error handling. Do not let a single worker failure silently propagate to the coordinator. Fail loudly, log the failure state, and let the coordinator decide whether to retry, fall back, or surface the error to the user.

If you want to see how this architecture applies to real B2B operations, the multi-agent AI skills breakdown for 2026 covers the specific competencies that separate functional pipelines from ones that hold up under production load. And if you are evaluating where agent automation fits relative to simpler chatbot approaches, this comparison for business analysts is worth reading before you commit to an architecture.

The full catalog of automation blueprints at ForgeWorkflows includes pre-built patterns for each of these stages, which can save significant time when you are trying to validate an architecture before writing everything from scratch.

Where This Roadmap Breaks Down

This three-stage path works for developers building task-specific agents on top of existing LLM APIs. It does not work well if your use case requires real-time data with sub-100ms latency, highly regulated outputs where every inference needs an audit trail, or domains where retrieval quality is fundamentally limited by sparse or low-quality source material.

RAG is only as good as your knowledge base. If your documents are inconsistent, outdated, or poorly structured, no amount of prompt engineering will produce reliable outputs. Fix the data before you build the agent.

Multi-agent orchestration also introduces coordination overhead that can exceed the value it adds for simple, linear tasks. Before you build a coordinator-worker system, ask whether a single well-prompted agent with tool access would solve the problem. Often it will.

What We’d Do Differently

Start evaluation before you start building. We have shipped agents where the evaluation framework came after the first working prototype. That order is backwards. Define what “correct” looks like, write 20 test cases, and run every prompt change against them from day one. Retrofitting evaluation onto a working system is harder than it sounds, and you will make worse decisions without it.

Version your vector store alongside your prompts. When retrieval quality degrades, the cause is usually a change to the embedding model, the chunking strategy, or the source documents. If you are not snapshotting your vector store state alongside your prompt versions, you cannot isolate which change caused the regression. Treat the vector store as a build artifact, not a live database.

Build the coordinator last, not first. Every multi-agent system we have seen that was designed coordinator-first ended up with workers that were too tightly coupled to the coordinator’s assumptions. Build each worker as a standalone, testable unit. Wire them together only after each one works independently. The coordinator should be the simplest component in the system, not the most complex.

Hermes Agent v0.13.0 Shipped 864 Commits — These 3 Primitives Are the Ones That Matter

On May 7, 2026, Nous Research shipped Hermes Agent v0.13.0 — codename “Tenacity” — with 864 commits, 588 merged PRs, and 295 contributors across the cycle. By May 10, Hermes had overtaken OpenClaw as the number-one agent on OpenRouter, processing 224 billion tokens per day. Every major newsletter ran the same story: the new Kanban view, the improved multi-agent board, the cleaned-up UI. That coverage is not wrong, but it is not the story that matters.

Underneath the Kanban there are three new primitives. They are easy to miss because they do not have their own release blog post, they are not in the feature highlights section of the changelog, and two of them are disabled by default. But they are the reason v0.13.0 is a different class of release from v0.12.x. They solve three specific failure modes that anyone who has run Hermes for more than a few hours in production will recognize immediately: goal drift, premature exit, and silent result corruption. Understanding what they are and how they compose is the difference between using Hermes as a demo toy and using it as infrastructure you can walk away from.

I have been running Hermes as part of my daily development loop on WOWHOW’s VPS since v0.11.0. I updated to v0.13.0 on May 8 and ran it for a week before writing this. What follows is what I found.

Context: What Hermes Is and Why These Numbers Matter

Hermes is Nous Research’s open-source agentic framework built on top of their Hermes model family. It is not a hosted product. You self-host it, connect it to your model provider of choice (Anthropic, OpenAI, Ollama, or any OpenAI-compatible endpoint), and it handles the agent loop, tool dispatch, memory, and multi-agent coordination. The closest analogues in the ecosystem are OpenClaw and the Anthropic Agents SDK, but Hermes has a distinctly different philosophy: it is designed for long-running, unsupervised runs where the agent must handle obstacles without human escalation.

The 864-commit figure is real. The changelog is genuinely extensive. But commit counts are noise. What I care about is: which changes affect reliability in production? The answer, after a week of use, is the three primitives I am going to describe. Everything else in v0.13.0 is either UI work, performance optimization, or bug fixes for edge cases I had not encountered.

The Three Failure Modes These Primitives Address

Before explaining the primitives, it helps to name the problems they solve. Each one is a real failure mode that shows up in agent logs if you run sessions longer than about 20 minutes.

Goal drift is when the agent forgets what it was originally asked to do. This is not hallucination in the traditional sense — the model has not invented a false fact. The goal was stated clearly in turn 1, but by turn 15 or 20, the agent is working on something adjacent to the original goal, or has reinterpreted the goal based on context accumulated during the session. In practice it looks like an agent asked to “refactor the payment module for idempotency” that ends up spending three turns refactoring unrelated logging code because the logging code came up in a tool call and seemed like it needed fixing.

Premature exit is when the agent returns control to the user when it hits an obstacle, rather than trying to work around it. This is the most common failure mode in short agent runs. The agent encounters a tool error, or an API returns an unexpected response, and instead of trying a different approach, it says something like “I encountered an error, please check X and restart the task.” From the user’s perspective, you launched an agent, walked away, came back, and it gave up.

Silent result corruption is the scariest one and the hardest to catch. In multi-agent setups, a worker agent returns a result that is factually wrong or unsupported by the evidence it found, and the orchestrator marks the task done and continues. No error is raised. The downstream output is built on a false foundation, and you may not discover this until the final result is in front of a human reviewer. In single-agent runs, this manifests as the agent stating a conclusion it did not actually verify.

These three failure modes are not edge cases. They are the default failure modes of any sufficiently capable agent running on a long task. The primitives in v0.13.0 are Nous Research’s answer to each one.

Primitive 1: /goal — Making the Goal a First-Class Runtime Object

The /goal command is the most architecturally significant change in v0.13.0. Before this release, the goal was a string in the system prompt or the first user turn. It existed in the context window, subject to the same attention dilution as everything else. By turn 12 of a long session, the model’s effective attention on the original goal string was competing with all the tool results, intermediate reasoning, and accumulated context from the session. Goal drift was the predictable result.

With /goal, the goal becomes a first-class primitive in the Hermes runtime. It is not stored in the context window. It is stored in a separate goal register that the runtime injects into every reasoning step as a structured prefix, independent of context window position. Every tool call, every sub-agent dispatch, every reasoning step is evaluated against the current goal before execution.

Setting a goal looks like this:

# Set the session goal
/goal Refactor the payment module for idempotency across all charge endpoints

# Inspect current goal at any point
/goal status

# Output:
# Goal: Refactor the payment module for idempotency across all charge endpoints
# Set at: turn 1
# Turns elapsed: 0
# Active sub-goals: none
# Last checked: --

The goal register is injected into the reasoning prefix like this (simplified from the v0.13.0 source):

[GOAL REGISTER]
Primary goal: Refactor the payment module for idempotency across all charge endpoints
Sub-goals: none
Turns elapsed since goal set: 14
Relevance check: REQUIRED before each tool dispatch

[REASONING STEP]
Current task: {agent_current_task}
Tool candidate: {tool_name}
Relevance to goal: {required_field}

The “relevance check: REQUIRED” line is not cosmetic. The Hermes runtime enforces it. If a tool dispatch does not include a relevance-to-goal field, the dispatch is blocked and the agent must re-reason about whether the tool call is actually advancing the primary goal. This forces explicit attention to the goal at every decision point, which is what eliminates drift.

Sub-Goal Inheritance

When the agent dispatches a sub-agent, the goal is inherited automatically. The sub-agent receives the parent’s primary goal as a read-only constraint in its own goal register. The sub-agent can set its own sub-goals, but those sub-goals must be consistent with the parent’s primary goal. Attempting to set a sub-goal that the runtime classifies as inconsistent with the parent goal raises a GoalConflict error and surfaces it to the orchestrator.

# Parent agent dispatches sub-agent for a specific subtask
dispatch_agent(
  task="Audit the charge() function for idempotency gaps",
  goal_inherit=True  # default in v0.13.0
)

# Sub-agent receives:
# [GOAL REGISTER]
# Primary goal (inherited, read-only): Refactor the payment module for idempotency
# Sub-goal: Audit the charge() function for idempotency gaps
# Constraint: sub-goal must advance primary goal

In practice, this means a sub-agent that wanders off to fix a different part of the codebase will be flagged before it can return a result that does not advance the parent’s goal. The constraint is enforced at result-return time, not just at dispatch time.

What Long Sessions Look Like Now

Before v0.13.0, I treated any Hermes session longer than about 25 turns as unreliable. The probability of goal drift past that point was high enough that I would check in manually every 20-25 turns and re-anchor the goal. With /goal enabled, I ran a refactoring session on WOWHOW’s WooCommerce integration layer that went to 73 turns without a drift incident. The agent stayed on the original goal throughout, and the /goal status checks I ran at turns 30, 50, and 70 all showed the primary goal unchanged and every tool dispatch recorded as “advances goal.”

That is the practical difference: sessions of 60+ turns become viable without supervision.

Primitive 2: The Ralph Loop — Ending Premature Exit

The Ralph loop is named in the changelog as “Ralph” without further explanation. Based on the implementation (visible in src/core/loop/ralph.py in the v0.13.0 source), it appears to reference Ralph as in “retry, adapt, loop, persist, halt” — though this may be backronym rationalization on the community’s part. What it does is more important than what it is named.

The Ralph loop is a structured retry-and-variant protocol that activates when the agent encounters an obstacle. Before v0.13.0, the default agent loop in Hermes was: attempt task, encounter obstacle, raise obstacle to user. The Ralph loop changes the obstacle response to: attempt task, encounter obstacle, generate variant approach, attempt variant, repeat until variants exhausted, only then escalate.

The loop structure in pseudocode:

def ralph_loop(task, goal, max_variants=5):
    attempt = execute(task)

    if attempt.success:
        return attempt.result

    variants = generate_variants(task, attempt.error, goal)

    for variant in variants[:max_variants]:
        # Re-ground against goal before each variant attempt
        if not advances_goal(variant, goal):
            continue

        result = execute(variant)

        if result.success:
            return result.result

        # Log failure and continue to next variant
        log_variant_failure(variant, result.error)

    # All variants exhausted — escalate
    raise ObstacleEscalation(
        original_task=task,
        variants_tried=variants,
        last_error=result.error
    )

Three things matter about this design.

First, variant generation happens against the goal. The agent does not generate arbitrary alternative approaches — it generates approaches that are evaluated for goal relevance before execution. This prevents the loop from “solving” the obstacle by switching to a task that sidesteps the original requirement.

Second, the loop re-grounds against the goal before each variant attempt. This is a separate check from the goal register injection. It is an explicit “does this variant actually advance the primary goal” evaluation that runs before any tool calls are made.

Third, escalation is genuinely a last resort. The agent only escalates to the user when all variants are exhausted. The default max_variants is 5, configurable per session. In my experience, most obstacle types are resolved within 2-3 variants. The escalation rate with Ralph loop enabled, compared to the previous default behavior, dropped from roughly 40% of obstacle encounters to roughly 8% in my usage over the week.

What the Loop Looks Like in Agent Output

With the Ralph loop active, obstacle encounters produce different output than before. Instead of a single “I encountered an error” message, you see a structured attempt log:

[RALPH LOOP] Obstacle encountered on task: Read payment/charge.py
Error: FileNotFoundError — path does not exist

[RALPH] Generating variants (goal: refactor payment module for idempotency)
  Variant 1: Search for charge.py across project directories
  Variant 2: Check git history for file moves
  Variant 3: Inspect payment/ directory structure

[RALPH] Attempting variant 1: Search for charge.py across project directories
  Result: Found at src/lib/payments/charge.py (moved in commit a3f9d12)
  Status: SUCCESS

[RALPH] Resuming primary task with corrected path

That log entry represents what would previously have been an escalation requiring manual user intervention. The agent found the file had moved, updated its internal path, and continued without surfacing anything to the user.

The Token Cost

The Ralph loop is not free. Each variant generation and variant attempt consumes tokens. In my sessions, enabling the Ralph loop increased token consumption per session by 20-40% on obstacle-heavy tasks. For frontier models (Opus 4.7, GPT-5.5), this is a real cost consideration. For smaller models running locally (Hermes-3-70B via Ollama), the token cost is less significant because inference cost per token is much lower.

The trade-off is straightforward: you pay more tokens per session, but sessions complete without requiring human intervention on routine obstacles. For unsupervised runs where operator time has a cost, the token trade-off is usually favorable. For interactive sessions where you are watching the agent, you might prefer to disable the Ralph loop and handle obstacles manually to avoid the token overhead.

Configuration:

# hermes.config.toml
[loop]
ralph_enabled = true
ralph_max_variants = 5          # default
ralph_log_level = "verbose"     # "verbose" | "summary" | "silent"
ralph_goal_check = true         # enforce goal relevance on each variant

Where It Does Not Help

The Ralph loop handles obstacles that have viable alternative approaches. It does not help when the obstacle is fundamental — for example, if a required API is down, generating five variant approaches to call the same API does not resolve the obstacle. Hermes handles this by classifying obstacles as “transient” (worth retrying with variants) or “structural” (no variant approach can succeed; escalate immediately). The classification uses the error type and a small heuristic model trained on the Hermes dataset. It is not perfect — I have seen transient errors misclassified as structural and escalated prematurely — but it works correctly about 85-90% of the time in my usage.

Primitive 3: The Hallucination Gate — Trust But Verify in Multi-Agent Work

The hallucination gate is the most operationally significant primitive for anyone running multi-agent boards. It solves silent result corruption, which I described earlier as the scariest failure mode. The gate is disabled by default in v0.13.0 and must be explicitly enabled per board or per agent.

The core mechanism is a verification trace requirement. Every worker agent, when it completes a task, must produce not just a result but a verification trace: a structured log of the evidence it examined, the reasoning it applied, and the specific data points that support the conclusion. The parent agent does not mark the task done until it has checked the verification trace and confirmed that the stated result is supported by the evidence in the trace.

A verification trace looks like this (from actual Hermes v0.13.0 output):

[VERIFICATION TRACE]
Task: Confirm that charge() endpoint is idempotent for duplicate request IDs
Result claimed: charge() is NOT idempotent — duplicate request IDs process twice

Evidence examined:
  1. src/lib/payments/charge.py:47 — no idempotency key check present
     Quote: "def charge(amount, currency, customer_id):"
     Classification: SUPPORTS result (no idempotency parameter)

  2. src/lib/payments/charge.py:89-103 — database insert without duplicate check
     Quote: "db.execute('INSERT INTO charges VALUES ...')"
     Classification: SUPPORTS result (no UNIQUE constraint check)

  3. tests/test_charge.py — searched for idempotency tests
     Result: No tests found matching 'idempotent' or 'duplicate_request'
     Classification: SUPPORTS result (no test coverage for idempotency)

Verification confidence: HIGH
Unsupported claims: none

The parent agent runs a gate check against this trace before accepting the result:

[HALLUCINATION GATE] Checking worker result: charge() not idempotent
  Result: charge() is NOT idempotent — duplicate request IDs process twice
  Trace evidence items: 3
  Supported by evidence: 3/3
  Confidence: HIGH
  Gate decision: ACCEPT

[ORCHESTRATOR] Task marked complete. Proceeding with: Add idempotency key parameter to charge()

When a result is not supported by the evidence in the trace, the gate rejects it and triggers an automatic re-attempt:

[HALLUCINATION GATE] Checking worker result: no rate limiting on payment API
  Result: Payment API has no rate limiting
  Trace evidence items: 2
  Supported by evidence: 1/2
  Unsupported claim: "API has no rate limiting"
    Evidence item 2 states: "Rate limit headers not present in test response"
    Gap: absence of rate limit headers in one response does not confirm absence of rate limiting
  Gate decision: REJECT

[ORCHESTRATOR] Worker result rejected. Reason: unsupported conclusion.
  Dispatching re-attempt with constraint: examine API documentation and error responses,
  not just response headers

That re-attempt is automatic. The orchestrator does not surface the rejection to the user. The worker retries with a more constrained task that forces it to look at better evidence. Only if the re-attempt also fails the gate does the orchestrator escalate.

Why This Enables Genuine Unsupervised Multi-Agent Work

The hallucination gate is what makes it reasonable to walk away from a multi-worker board and trust the output. Before v0.13.0, multi-agent boards on Hermes produced results I had to review manually before acting on them. Individual workers would state conclusions that looked plausible but were not well-supported by what they had actually examined. The orchestrator had no way to detect this — it just accepted worker results and passed them downstream.

With the gate enabled, the verification requirement forces workers to build their reasoning transparently. A worker cannot state “X is true” without also providing the evidence trail that supports the claim. The gate checks that trail mechanically and rejects conclusions that outrun the evidence.

In a week of running multi-agent boards on WOWHOW’s codebase, I had 3 gate rejections out of 47 completed worker tasks. Two of those rejections caught real errors: a worker that concluded a function was unused based on searching only one directory (it was used in another), and a worker that stated an API call would succeed based on documentation that was outdated. Both would have produced downstream errors if accepted. The gate caught them before the orchestrator built on them.

Configuration and the Self-Improvement Default

The gate is configured at the board level:

# hermes.config.toml
[hallucination_gate]
enabled = true
confidence_threshold = "HIGH"    # "HIGH" | "MEDIUM" | "LOW"
auto_retry_on_reject = true
max_retries = 2
require_evidence_items = 2       # minimum evidence items in trace
opaque_rejection_mode = false    # set true to hide rejection details from workers

One configuration option deserves special note: opaque_rejection_mode. When this is false (the default), the worker receives the full gate rejection details on retry — it knows exactly why its result was rejected and what evidence gap it needs to address. When it is true, the worker receives only “result rejected, retry” without the specific reason. The documentation notes that opaque mode can be used to prevent workers from “gaming” the gate by manufacturing evidence that technically satisfies the gate criteria without genuinely supporting the conclusion.

There is also a configuration option for self-improvement that is hidden in the default config template and not mentioned in the main documentation: gate_self_improvement = false. When enabled, the gate analyzes its own rejection decisions and updates its checking heuristics over the session to improve accuracy. This is disabled by default because in multi-session use it can produce drift in gate behavior that is hard to reason about. I have not tested it in production. I mention it because it exists and because the default config hides it, which is the kind of thing that can be surprising to discover mid-session.

How the Three Primitives Compose

The primitives are designed to work together, and their interaction is where the real reliability improvement comes from. In isolation, each one addresses a specific failure mode. Together, they form a coherent reliability layer for the agent loop.

The composition model is:

  1. /goal sets the target. Everything the agent does is evaluated against this target. The target is injected at every reasoning step, not just stored in context.

  2. The Ralph loop drives toward the target. When the agent hits an obstacle, it generates and tries variants rather than giving up. Each variant is checked against the goal before execution, so the loop cannot solve obstacles by abandoning the original task.

  3. The hallucination gate keeps the drive honest. Results from workers must be backed by evidence. The gate rejects conclusions that outrun what the agent actually examined, forcing the loop to be accurate rather than merely productive.

A minimal workflow that uses all three:

# Set the primary goal
/goal Audit payment module for idempotency issues and generate a remediation plan

# Configure the session
/config ralph_enabled=true ralph_max_variants=4
/config hallucination_gate=true gate_confidence=HIGH

# Launch a multi-agent board
/board create payment-audit

# Dispatch workers
/board dispatch worker-1 "Audit charge() for idempotency gaps"
/board dispatch worker-2 "Audit refund() for idempotency gaps"
/board dispatch worker-3 "Check test coverage for idempotency scenarios"

# Walk away
# The orchestrator will:
# 1. Run workers with goal inheritance
# 2. Apply Ralph loop to any obstacles each worker encounters
# 3. Gate-check all worker results before accepting them
# 4. Synthesize accepted results into remediation plan
# 5. Surface only genuine escalations that require human judgment

That workflow, on a moderately complex codebase, will run to completion without human intervention in the vast majority of cases. Before v0.13.0, the same workflow had a meaningful probability of stalling on worker obstacles, drifting from the original goal, or returning results built on unsupported claims from a worker that hallucinated its findings.

Where It Broke: Real Limitations in the First Week

I am not going to claim these primitives are production-ready without caveats. Here is where I ran into genuine problems in the first week.

Ralph Loop Token Cost on Frontier Models

The 20-40% token overhead I mentioned is significant when running on Opus 4.7 or GPT-5.5 at full price. A session that would have cost $3.20 with v0.12.x costs $4.20-$4.50 with the Ralph loop enabled. For obstacle-heavy tasks in large codebases, I have seen sessions run $6-7 instead of $4. This is not a deal-breaker, but it is a real cost increase that affects whether you route tasks to frontier models or smaller models.

My current approach: enable Ralph on sessions running local models (Hermes-3-70B via Ollama) without hesitation. For frontier-model sessions, enable Ralph only on tasks where premature exit would require significant manual re-setup time — tasks where the operator-time cost of a stall exceeds the token cost of the loop.

/goal Does Not Support Compound Goals

The goal register holds a single primary goal string. If your actual objective is compound — “audit for idempotency AND ensure no performance regression” — you cannot represent both conditions as coordinated first-class goals. The workaround is to set sub-goals and manually track their relationship, but this is clunky. I have seen compound goals cause issues where the agent fully satisfies one dimension of the goal and considers the task complete without addressing the second dimension.

This is a known limitation in the v0.13.0 milestone notes. Compound goal support is listed as a v0.14.0 target. For now, the workaround is to decompose compound goals into sequential sessions with single goals each.

Gate Rejections Can Be Opaque

Even with opaque_rejection_mode = false, gate rejection messages can be hard to interpret. The gate produces structured rejection output, but the “evidence gap” classification is sometimes correct in form but unhelpful in practice. I had one rejection where the gate flagged an evidence gap that was actually a naming inconsistency between the worker’s terminology and the gate’s expected schema. The worker had the right evidence but used different field names in the trace, and the gate rejected the result as unsupported. The worker then retried with more evidence (correctly), but it also changed its conclusion slightly to match the additional evidence, which introduced a small inaccuracy in the final output.

This is an edge case, but it illustrates that the gate is not infallible. It can reject valid results and accept invalid ones (though the false-negative rate — accepting invalid results — is much lower than accepting-without-gate was before v0.13.0).

Self-Improvement Is Hidden

I mentioned gate_self_improvement above. The fact that it exists but is hidden from the default config template is the kind of configuration footgun that bites you when someone runs hermes config --defaults --reset and the hidden setting is not in the defaults file. If you are deploying Hermes in a team environment, explicitly set every gate configuration option in your config file so the behavior is documented and not dependent on what the defaults happen to be.

What I Kept After a Week

After a week with v0.13.0, here is my actual running configuration on WOWHOW’s VPS:

# /root/storefront/hermes/hermes.config.toml

[loop]
ralph_enabled = true
ralph_max_variants = 4          # reduced from default 5; faster escalation on genuinely hard obstacles
ralph_log_level = "summary"     # verbose is too noisy for regular sessions
ralph_goal_check = true

[hallucination_gate]
enabled = true
confidence_threshold = "HIGH"
auto_retry_on_reject = true
max_retries = 2
require_evidence_items = 2
opaque_rejection_mode = false
gate_self_improvement = false   # explicitly disabled; documented for the team

[goal]
inject_frequency = "every_step"  # default; inject goal at every reasoning step
sub_goal_conflict_check = true
goal_drift_alert_threshold = 10  # alert if no goal-relevant tool calls in 10 turns

The goal drift alert is useful. It does not stop the agent — it sends a notification to the Telegram bot that is already wired into my monitoring stack — but it gives me a signal to check in if the agent has gone 10 turns without doing anything that advances the primary goal. In practice, this fires about once per 5-6 long sessions, and when it fires, it is usually catching something worth looking at.

What I Left Out

I am not using the full Kanban board UI that was the centerpiece of the v0.13.0 marketing. I run Hermes headlessly via the CLI and the REST API. The Kanban is a useful visualization if you are managing multi-agent boards with human collaborators, but for solo unsupervised runs, the UI layer adds operational overhead (running a browser, managing the Hermes frontend container) without providing reliability benefits. The three primitives work identically in headless mode.

I am also not using the new “agent memory” features that shipped in v0.13.0. Hermes now has a persistent memory layer (based on a local vector store) that agents can write to and retrieve from across sessions. This is genuinely useful for certain use cases — agents that accumulate institutional knowledge about a codebase over many sessions — but I use Graphify for codebase knowledge graphs and have not found Hermes memory to offer enough incremental value over that to switch. This may change in v0.14.0 if the memory layer gets better integration with the goal register.

The Reliability Story Is These Three Primitives

v0.13.0 shipped 864 commits. Most of those commits are real improvements. The Kanban is genuinely better. Performance is up. Bug fix count is high. But if you are evaluating whether to upgrade from v0.12.x, or whether to invest in self-hosting Hermes for production use, the answer depends almost entirely on whether these three primitives address failure modes you are experiencing.

Goal drift, premature exit, and silent result corruption are the three most common ways that capable agent frameworks fail in production on long or complex tasks. The v0.13.0 primitives address each one with a mechanism that is well-designed and works as described in most cases. The limitations are real — compound goals, token cost on frontier models, opaque gate rejections — but they are manageable and do not undermine the core reliability improvement.

The Kanban is the UI story. /goal, the Ralph loop, and the hallucination gate are the reliability story. Those are the ones that matter.

Upgrade and Configuration Notes

If you are upgrading from v0.12.x, note that all three primitives require explicit opt-in. None of them are active by default. The upgrade does not change your existing behavior; you have to enable each primitive in your config file or via session commands.

# Upgrade
pip install hermes-agent==0.13.0

# Or via Docker
docker pull nousresearch/hermes-agent:0.13.0

# Minimal config to enable all three primitives
cat >> hermes.config.toml << EOF
[loop]
ralph_enabled = true

[hallucination_gate]
enabled = true

[goal]
inject_frequency = "every_step"
EOF

The v0.12.x config format is fully compatible with v0.13.0. No migration is required. New configuration blocks are additive.

One final note: if you are running Hermes connected to Claude via the Anthropic API, v0.13.0 is the first version that natively handles the Claude extended thinking budget parameter (thinking.budget_tokens). The Ralph loop variant generation, when running on Claude Opus 4.7, uses extended thinking for variant quality if you have budget tokens configured. This is optional and documented in the v0.13.0 API reference, but it is worth knowing about if you are already using extended thinking in your Anthropic API calls — Hermes will respect the budget parameter you pass rather than using its own default.

The three primitives are the reason I upgraded the day after the release dropped. They are the reason I will keep running Hermes as daily infrastructure rather than treating it as a demo-only tool. If you are on v0.12.x and experiencing goal drift, premature exits, or multi-agent result quality issues, v0.13.0 with these three primitives enabled is the direct answer to those problems.

Originally published at wowhow.cloud

A .NET Dinosaur in Web3. Day 7 — First connect

Intro

This day is a bit different from the previous ones. Initially, the idea was simple — one contract per day. But Web3 is not just about contracts and blockchain. There are other layers — UI, integration, the way everything connects together. At some point it became obvious: it makes more sense to start structuring the project early, instead of treating each part in isolation. As a developer who is getting close to an architect level — and someone who enjoys microservice architecture — I got curious: how are these projects actually structured?

A contract is just one piece. A dApp is a system. I assume the same principles apply here — some form of clean architecture, separation of concerns, clear boundaries. And for something like WishList Chain, it felt important to start thinking about the structure from the beginning.

At that point, I started thinking not just about the contract itself, but about the structure of the whole project. Because Web3 is clearly not only about writing smart contracts. There is always a frontend, some kind of interaction layer, maybe scripts or bots, and potentially even a backend later on. All of these parts are connected, whether you plan for it or not.

So the question became less about “what to build next” and more about “how to structure it properly from the beginning.”

That’s where the idea of using a monorepo came in.

Why Monorepo?

I decided to approach this a bit differently. Usually, I create separate repositories by responsibility (the “S” in SOLID), but not this time.

Here the picture is clearer. The contract and the frontend are tightly connected. Any change in the contract — new fields, updated logic, even a different address — will require changes in multiple places. That means more manual work, more context switching, and more chances to break something.

Better to keep things as simple as possible.

So instead of splitting things too early, I decided to keep everything in one place. A single repository, but clearly separated layers inside it:

wish-list-chain/
├── apps/
│   └── web/       ← Next.js 15
├── contracts/     ← Hardhat
├── package.json
└── .env

From a structural point of view, it already feels closer to a real system rather than a set of experiments.

I know this goes a bit against how I usually structure things. Normally, I prefer to separate repositories by responsibility — the “S” in SOLID. It keeps boundaries clear and makes scaling easier later. But in this case, it felt like the separation would introduce more friction than value. The responsibilities are still separated — just not at the repository level.

Project Stack

Before the code — a quick map of what we’re working with and why.

Tool Role .NET analogy
Next.js 15 (App Router) Frontend framework ASP.NET Core MVC
wagmi 2 React hooks for blockchain SDK wrapper for Web3 calls
viem 2 Low-level Ethereum client HttpClient for the blockchain
RainbowKit Wallet connection UI OAuth login button
@tanstack/react-query Async state management No direct equivalent
WalletConnect / Reown Multi-wallet protocol OAuth provider

Theory — A Little Bit

wagmi sits on top of viem. viem handles the low-level blockchain calls. wagmi provides React hooks like useAccount, useReadContract, useWriteContract. You can drop down to viem when you need more control, but most of the time wagmi is enough.

RainbowKit is just a UI layer on top of wagmi — the modal, the button, the wallet list. It doesn’t do any blockchain work itself.

What Clicked

Next.js 15 App Router makes everything a Server Component by default. wagmi hooks rely on React state and browser APIs — they can’t run on the server. Any component that calls useAccount, useReadContract, or renders <ConnectButton /> needs 'use client' at the top. Otherwise, the code looks correct — but simply doesn’t work.

ConnectKit doesn’t support React 19 yet.

I actually started with ConnectKit — clean UI, good docs, everything looked straightforward. It failed immediately. Peer dependency error: it requires React 17 or 18, while Next.js 15 already ships with React 19. So that path just… stopped there.

This is the current state of the Web3 frontend ecosystem: some libraries are ahead, some are behind. Check React version compatibility before installing anything.

Downgrading React didn’t feel right. So I kept React 19 and aligned the rest of the stack around it — wagmi 2.x ended up being the stable choice.

RainbowKit requires wagmi 2. wagmi 3 is out but RainbowKit hasn’t released a compatible version yet. Pinning wagmi to version 2 for now. This will resolve eventually — until then, mixing versions breaks the dependency tree.

The Result

<ConnectButton /> renders. Click it — RainbowKit modal opens with MetaMask, WalletConnect, and others. Connect MetaMask — wallet address and balance appear.

That’s a Next.js 15 app reading live data from the Sepolia blockchain through a connected wallet. No backend. No API. The blockchain is the data source.

Next: read totalDreamPower directly from the WishlistV3 contract using useReadContract.

Repo: github.com/alena-dev-soft/wish-list-chain

Stage: Dinosaur 🦕 — frontend connected. Blockchain is the backend.

Integrating Pakistani Businesses with the FBR Digital Invoicing API

If you build or maintain software for Pakistani businesses, FBR Digital Invoicing integration is now in your backlog whether you wanted it or not. Under SRO 709(I)/2025, every sales-tax-registered person in Pakistan must transmit invoices to FBR in real time via the Digital Invoicing API operated by PRAL (Pakistan Revenue Automation).

This post is the practical developer walkthrough I wish existed when I first built integrations against this API. We’ll cover the architecture, the auth flow, the JSON payload, sandbox testing for the 28 mandatory scenarios, retry logic for FBR’s outages, and the going-to-production checklist.

The architecture in 30 seconds

Your app → PRAL Digital Invoicing API → FBR core system
              ↓
        IRN + QR code returned to you
              ↓
        Print on the customer's invoice

Three endpoints matter:

  • validateinvoicedata — pre-flight check before live submission
  • postinvoicedata — actual invoice submission, returns IRN + QR code
  • cancelinvoicedata — cancellation within the 72-hour correction window (post April 2026)

You authenticate with a bearer token issued via the FBR IRIS portal per registered NTN.

Step 1: Get your bearer token

  1. Log in to iris.fbr.gov.pk with the business’s CNIC/NTN
  2. Navigate to Digital Invoicing → Integration Mode
  3. Select “Proceed with PRAL as Licensed Integrator”
  4. The portal generates a bearer token tied to that NTN

The token is opaque and long-lived (it doesn’t expire frequently). Store it encrypted — under no circumstances commit it to source control or log it in plain text. AES-256 at rest is the minimum standard.

Step 2: Construct the invoice payload

FBR expects a strict JSON structure. Here’s a minimal but complete payload for a B2B taxable supply:

{
  "invoiceType": "Sale Invoice",
  "invoiceDate": "2026-05-16",
  "sellerNTNCNIC": "1234567",
  "sellerBusinessName": "Acme Trading (Pvt) Ltd",
  "sellerProvince": "Punjab",
  "sellerAddress": "Plot 12, Lahore",
  "buyerNTNCNIC": "7654321",
  "buyerBusinessName": "Beta Industries (Pvt) Ltd",
  "buyerProvince": "Sindh",
  "buyerAddress": "Industrial Area, Karachi",
  "buyerRegistrationType": "Registered",
  "invoiceRefNo": "ACM-2026-0001",
  "items": [
    {
      "hsCode": "1234.5678",
      "productDescription": "Industrial pump model X-200",
      "rate": "18%",
      "uoM": "Numbers, pieces, units",
      "quantity": 5,
      "totalValues": 50000,
      "valueSalesExcludingST": 42372.88,
      "fixedNotifiedValueOrRetailPrice": 0,
      "salesTaxApplicable": 7627.12,
      "salesTaxWithheldAtSource": 0,
      "extraTax": 0,
      "furtherTax": 0,
      "sroScheduleNo": "",
      "fedPayable": 0,
      "discount": 0,
      "saleType": "Goods at Standard Rate (default)",
      "sroItemSerialNo": ""
    }
  ]
}

Critical fields to get right:

  • sellerNTNCNIC and buyerNTNCNIC — exactly as registered with FBR; mismatches return validation errors
  • hsCode — must match the actual product category (FBR validates against their HS Code database)
  • rate — string format with % sign, not a number
  • saleType — one of FBR’s predefined values (e.g., “Goods at Standard Rate (default)”, “3rd Schedule Goods”, “Steel Melting and Re-Rolling”)
  • valueSalesExcludingST and salesTaxApplicable — must mathematically reconcile to totalValues

If your software can’t render these from your existing invoice data model, you have an integration bug, not an FBR problem.

Step 3: Submit the invoice

curl -X POST 'https://gw.fbr.gov.pk/di_data/v1/di/postinvoicedata' 
  -H 'Authorization: Bearer YOUR_PRAL_TOKEN' 
  -H 'Content-Type: application/json' 
  -d @invoice.json

Or in Python:

import requests
import os

PRAL_TOKEN = os.environ['PRAL_BEARER_TOKEN']
ENDPOINT = 'https://gw.fbr.gov.pk/di_data/v1/di/postinvoicedata'

response = requests.post(
    ENDPOINT,
    headers={
        'Authorization': f'Bearer {PRAL_TOKEN}',
        'Content-Type': 'application/json'
    },
    json=invoice_payload,
    timeout=30
)

if response.status_code == 200:
    result = response.json()
    irn = result['invoiceNumber']
    qr_code = result['QRCode']  # base64-encoded image
    # Persist IRN + QR code with your invoice record
else:
    # Handle error (see error handling section below)
    pass

Step 4: Print the IRN and QR code

The IRN and QR code must appear on the invoice you give the customer. Without them, the invoice is legally invalid — even if you have a paper copy.

Your invoice template needs:

  • The IRN clearly labelled (e.g., “FBR Reference: 12345678901234”)
  • The QR code rendered at minimum 2cm × 2cm with sufficient contrast
  • A note: “Verify this invoice at fbr.gov.pk/online-invoice-verification”

Most stack PDFs use libraries like ReportLab (Python) or PDFKit (Node) to embed the base64 QR code directly.

Step 5: Sandbox first, always

FBR provides a sandbox environment at https://gw.fbr.gov.pk/di_data/v1/di/postinvoicedata_sb for testing. You must pass all 28 mandatory test scenarios before going to production.

The 28 scenarios fall into seven categories:

  1. Standard sales (5 scenarios) — basic B2B/B2C at 18%
  2. Third Schedule goods (3 scenarios) — retail-price-based tax
  3. Reduced-rate and zero-rated supplies (4 scenarios) — 1%/5%/10%/15% rates plus zero-rated exports
  4. Exempt supplies (2 scenarios) — Sixth Schedule items
  5. Further tax and withholding (4 scenarios) — 3% further tax for unregistered buyers
  6. Returns, debit and credit notes (4 scenarios) — linkage to original IRN
  7. Special cases (6 scenarios) — multi-currency, FED on services, advance payments, exports

Most integration failures happen on scenarios 3 (reduced rates) and 6 (returns linkage). Build automated tests for these first.

Step 6: Error handling and retry logic

FBR’s API isn’t always up. You need queue-and-retry logic in production.

A reasonable pattern:

class FBRSubmissionService:
    MAX_RETRIES = 5
    RETRY_DELAYS = [1, 5, 30, 120, 600]  # seconds, exponential

    def submit_invoice(self, invoice_id):
        invoice = Invoice.objects.get(id=invoice_id)
        payload = self.build_payload(invoice)

        for attempt, delay in enumerate(self.RETRY_DELAYS):
            try:
                resp = requests.post(
                    self.endpoint,
                    headers={'Authorization': f'Bearer {self.token}'},
                    json=payload,
                    timeout=30
                )

                if resp.status_code == 200:
                    result = resp.json()
                    invoice.irn = result['invoiceNumber']
                    invoice.qr_code = result['QRCode']
                    invoice.status = 'submitted'
                    invoice.save()
                    return True

                if resp.status_code == 400:
                    # Validation error — log + don't retry
                    invoice.status = 'validation_error'
                    invoice.error_details = resp.json()
                    invoice.save()
                    return False

                if resp.status_code in (500, 502, 503, 504):
                    # Transient error — retry
                    time.sleep(delay)
                    continue

            except requests.Timeout:
                time.sleep(delay)
                continue

        # Exhausted retries — flag for manual review
        invoice.status = 'requires_manual_review'
        invoice.save()
        return False

Critical patterns:

  • Idempotency — your invoiceRefNo should be unique per submission so FBR won’t double-process
  • Persistent queue — if your app crashes, pending submissions should resume on restart (use a database-backed queue, not in-memory)
  • Audit log — every submission attempt, response, retry should be logged with timestamps for compliance review
  • Alerting — set up alerts when invoices spend more than 1 hour in ‘pending’ state

Step 7: The 72-hour correction window

Under the April 2026 Sales Tax General Order No. 01 of 2026, invoices can be cancelled, deleted, or edited within 72 hours of issuance without Commissioner approval. After 72 hours, you need prior approval — slow.

Your software needs:

  • A timestamp-driven “editable” flag on every invoice
  • A correction endpoint that resubmits with reference to the original IRN
  • A clear UI hint that says “X hours remaining to edit without approval”

Don’t let users edit invoices after 72 hours via your normal flow — force them through the Commissioner-approval path.

Step 8: Production deployment checklist

Before flipping the production switch:

  • [ ] All 28 sandbox scenarios passed
  • [ ] Bearer token stored encrypted (AES-256 at rest)
  • [ ] Token not logged in plain text anywhere
  • [ ] Idempotent invoiceRefNo generation
  • [ ] Queue-and-retry with exponential backoff
  • [ ] Persistent queue (survives app restart)
  • [ ] Audit log of every API call
  • [ ] Alerting on stuck invoices (>1 hour pending)
  • [ ] Monitoring of API response time (95th percentile)
  • [ ] Daily reconciliation: invoice counts you sent vs counts in FBR’s portal
  • [ ] Backup plan for FBR downtime (when systems will queue locally and replay)
  • [ ] Per-business sandbox/production toggle if you serve multiple clients
  • [ ] QR code rendering tested on actual printed invoices (contrast, scannability)

Most integrations break in production on the reconciliation step — your audit log says you sent 1,000 invoices today, but FBR’s portal shows 998. The missing two were rejected silently for some edge case. Catch these daily.

Step 9: Should you build this or use a managed platform?

Honest math:

  • Building it yourself: ~80–200 hours upfront, plus 5–15 hours per month maintenance (FBR updates the API several times a year)
  • Using a managed platform: Rs 1,500–8,000/month per business, zero engineering time

For a single-business integration, building yourself is defensible — you control everything, no vendor lock-in. For multi-business scenarios (tax consultants managing 10–100 clients), managed platforms always win on time-to-value.

I run Tallied, which handles this for Pakistani tax consultants. We charge Rs 1,500 per client business per month (wholesale tier) with white-label custom domains and a multi-client dashboard. For developers evaluating: we use the exact same PRAL API documented above, but consolidate multi-business token management, queue-and-retry, and the 28 sandbox scenarios into one interface.

For more context on the regulatory side of FBR Digital Invoicing — who must integrate, deadlines, penalties under Section 33, and how to choose the right software — see the full guide and the software comparison on the Tallied blog.

Closing notes for developers

The FBR Digital Invoicing API is well-designed by Pakistani government API standards — versioned, JSON-based, OAuth-token authenticated, with a real sandbox. The 28 scenarios are tedious but mostly straightforward. The biggest production gotchas are silent rejection, FBR downtime, and managing tokens across multiple registered persons if you’re building multi-tenant.

Build idempotent. Log everything. Reconcile daily. Encrypt the token. Run all 28 scenarios in CI.

And if you ever ship anything in production against this API: print the IRN large enough that the chai-walla at your customer’s office can read it. The compliance officer scanning your invoice with a phone camera will thank you.

Cumhurbaşkanı Erdoğan: Terörle Mücadelede Harcanan Kaynaklar Eğitim ve Teknolojiye Aktarılsın

Cumhurbaşkanı Recep Tayyip Erdoğan, AK Parti Gençlik Kolları’nın düzenlediği ‘Bir Gençlik Şöleni’nde yaptığı konuşmada, terörle mücadele için ayrılan kaynakların artık eğitim, bilim, üretim ve teknoloji gibi alanlara yönlendirilmesi gerektiğini vurguladı. Annelerin yüreğine ateş düşmesini istemediklerini belirten Erdoğan, gençlerin geleceğine yatırım yapılması gerektiğini ifade etti.

Erdoğan: Türkiye eski Türkiye değil, yıldızı parlıyor

Cumhurbaşkanı Recep Tayyip Erdoğan, “Dünya nasıl eski dünya değilse, Türkiye’de eski Türkiye değil. Bugün her alanda yıldızı parlayan bir Türkiye var. Dünyada krizler yaşanırken dimdik ayakta duran bir Türkiye var. Masada sözü dinlenen, sahada gücü hissedilen bir Türkiye var.