<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alizamin Jafarli</title>
    <description>The latest articles on DEV Community by Alizamin Jafarli (@alizaminj).</description>
    <link>https://dev.to/alizaminj</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F295001%2F042b7e81-fafb-43b7-a4ef-61b7f32c0a0b.jpg</url>
      <title>DEV Community: Alizamin Jafarli</title>
      <link>https://dev.to/alizaminj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alizaminj"/>
    <language>en</language>
    <item>
      <title>Stop Putting Secrets in Plaintext</title>
      <dc:creator>Alizamin Jafarli</dc:creator>
      <pubDate>Mon, 24 Aug 2026 22:45:40 +0000</pubDate>
      <link>https://dev.to/alizaminj/stop-putting-secrets-in-plaintext-4khd</link>
      <guid>https://dev.to/alizaminj/stop-putting-secrets-in-plaintext-4khd</guid>
      <description>&lt;p&gt;Most local dev setups end up with some secret — an API key, a cloud credential, a database password — sitting in a plaintext file on disk indefinitely. Here's a simple pattern that avoids that, using AWS credentials as the example.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with the usual approaches
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A credentials file (e.g. &lt;code&gt;~/.aws/credentials&lt;/code&gt;)&lt;/strong&gt; — plaintext, no expiry, no prompt. Anyone with filesystem access (malware, a compromised dependency, a careless backup, a stolen unencrypted disk) reads it instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A &lt;code&gt;.env&lt;/code&gt; file "just for now"&lt;/strong&gt; — inevitably ends up committed once someone forgets it's there, or pasted into a chat while debugging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets exported in your shell profile&lt;/strong&gt; — same problem, just moved into &lt;code&gt;.bashrc&lt;/code&gt; or &lt;code&gt;.zshrc&lt;/code&gt;, still plaintext, still readable by anything running as your user.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The common thread: none of these require &lt;em&gt;proving you're you&lt;/em&gt; at the moment of use. The secret just sits there, decrypted, waiting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: password manager + directory-scoped env loading
&lt;/h2&gt;

&lt;p&gt;Store the secret in a system built for secrets — a password manager — and only materialize it into the environment for the duration of a shell session, gated behind your master password.&lt;/p&gt;

&lt;p&gt;A password manager like &lt;strong&gt;Bitwarden&lt;/strong&gt; gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encrypted-at-rest storage, synced across devices.&lt;/li&gt;
&lt;li&gt;A CLI (&lt;code&gt;bw get item&lt;/code&gt;, &lt;code&gt;bw unlock --raw&lt;/code&gt;) that scripts easily.&lt;/li&gt;
&lt;li&gt;A clean separation between &lt;em&gt;login&lt;/em&gt; (proving identity to Bitwarden's servers) and &lt;em&gt;unlock&lt;/em&gt; (decrypting the vault locally with the master password) — unlock is what gates access, and it's required every time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;direnv&lt;/strong&gt; gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatic loading/unloading of environment variables scoped to a directory. &lt;code&gt;cd&lt;/code&gt; in, get the vars; &lt;code&gt;cd&lt;/code&gt; out, they're gone.&lt;/li&gt;
&lt;li&gt;A trust boundary: &lt;code&gt;.envrc&lt;/code&gt; files must be explicitly approved (&lt;code&gt;direnv allow&lt;/code&gt;) before they execute, so a malicious &lt;code&gt;.envrc&lt;/code&gt; in a cloned repo can't silently run code.&lt;/li&gt;
&lt;li&gt;No setup script to remember — it's automatic on directory entry.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together: the secret never touches disk in plaintext. It lives encrypted in Bitwarden, and only exists as an environment variable for the lifetime of a shell session in one directory, after an explicit unlock.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: AWS credentials
&lt;/h2&gt;

&lt;p&gt;Store the key as a normal Login item (or a secure note) in Bitwarden (e.g. named &lt;code&gt;aws-iam-keys&lt;/code&gt;) with custom fields &lt;code&gt;aws_access_key_id&lt;/code&gt; and &lt;code&gt;aws_secret_access_key&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then a project's &lt;code&gt;.envrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;BW_ITEM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"aws-iam-keys"&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BW_SESSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;bw unlock &lt;span class="nt"&gt;--raw&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;item_json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;bw get item &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BW_ITEM&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--session&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BW_SESSION&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$item_json&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;log_error &lt;span class="s2"&gt;"Could not fetch Bitwarden item '&lt;/span&gt;&lt;span class="nv"&gt;$BW_ITEM&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;bw_field&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$item_json&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; name &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'.fields[]? | select(.name == $name) | .value // empty'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;bw_field aws_access_key_id&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;bw_field aws_secret_access_key&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;cd&lt;/code&gt;-ing into the project prompts for the Bitwarden master password once and exports the two env vars that any AWS SDK or CLI already knows how to read. The same pattern works for any secret: swap the item name and field names, export whatever env vars the tool in question expects (a database URL, an API token, whatever).&lt;/p&gt;

&lt;p&gt;One thing worth noting: direnv only re-executes &lt;code&gt;.envrc&lt;/code&gt; when the directory changes or the file itself is edited — it doesn't re-run on every command within the same shell. So "prompt once per shell/directory load" isn't something you have to build; it's just how direnv already works. It's tempting to cache the unlocked &lt;code&gt;BW_SESSION&lt;/code&gt; to a file so multiple terminal tabs share one unlock, but that just trades one problem for another — now there's a live decryption key sitting on disk. Re-entering the master password once per new terminal is a fine trade for keeping no secret material on disk at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;For any local secret, ask whether it's ever decrypted-and-idle on disk. A password manager + directory-scoped env loading means the secret only exists in memory, for as long as you're in the project, gated behind an explicit unlock — a small amount of setup for a meaningfully smaller attack surface than a credentials file that just sits there forever.&lt;/p&gt;

&lt;p&gt;What's your setup for local secrets — do you rely on a cloud secrets manager instead, or something else entirely? Curious to hear in the comments.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>Choosing the Right Agentic AI Framework on AWS</title>
      <dc:creator>Alizamin Jafarli</dc:creator>
      <pubDate>Fri, 14 Aug 2026 23:40:55 +0000</pubDate>
      <link>https://dev.to/alizaminj/choosing-the-right-agentic-ai-framework-on-aws-160n</link>
      <guid>https://dev.to/alizaminj/choosing-the-right-agentic-ai-framework-on-aws-160n</guid>
      <description>&lt;p&gt;Here are three simple, architectural rules of thumb to help you choose the right path, along with a look at how to bridge the gap between custom local code and secure cloud production.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Rule 1: Lean on Configuration First, Code Second&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before you write a single line of state-management code, ask yourself: Does my agent need custom orchestration logic, or can it be defined by instructions and schema-driven tools?&lt;/p&gt;

&lt;p&gt;If you want a fully managed experience where the cloud provider handles the underlying infrastructure, scaling, and orchestrating loop, Amazon Bedrock Agents is your starting point.&lt;/p&gt;

&lt;p&gt;With Bedrock Agents, developer effort is shifted from writing boilerplate orchestrators to configuring action groups and integrating knowledge bases. You define the agent's instructions, hook up your APIs, attach your guardrails, and let Bedrock coordinate the reasoning loops behind the scenes. It has a low learning curve and requires zero infrastructure provisioning, making it ideal for teams that want production-ready capabilities without a massive development overhead.&lt;/p&gt;

&lt;p&gt;When to use it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to deploy rapidly using a configuration-driven approach.&lt;/li&gt;
&lt;li&gt;Your agent primarily interacts with enterprise knowledge bases and standard REST APIs.&lt;/li&gt;
&lt;li&gt;You do not have the in-house resources to manage custom containerized orchestrators.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Rule 2: Match the Framework to the State Machine&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If a managed configuration is too restrictive and you need to write custom code, your next decision is about how your agents should coordinate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Deep AWS-Native Integration: Strands Agents&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your organization is heavily invested in AWS and you want custom code that integrates natively with the cloud ecosystem, Strands Agents is a premier choice. It offers the strongest AWS integration along with excellent support for foundation models like Anthropic Claude and Amazon Nova. It balances powerful autonomous workflow capabilities with moderate learning curves, making it an excellent default for enterprise-scale developers on AWS.&lt;/p&gt;

&lt;h4&gt;
  
  
  For High State Complexity: LangGraph
&lt;/h4&gt;

&lt;p&gt;If your application requires a highly complex, custom state machine with cyclical loops, branching logic, and precise control over the conversation flow, LangGraph (and LangChain) is the gold standard. It is unmatched in workflow complexity and multimodal support, though it comes with a steep learning curve.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Role-Based Collaboration: CrewAI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your project depends on role-playing, where multiple specialized agents (like a researcher, a writer, and a code reviewer) must collaborate asynchronously to execute a sequential pipeline of tasks, CrewAI is a natural fit. It simplifies team-oriented architectures, allowing you to orchestrate collaborative agent "crews" with clear roles.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Rule 3: The Host Matters as Much as the Framework&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A common mistake is assuming that choosing an open-source framework like CrewAI or LangGraph means you have to build, scale, and secure your own hosting infrastructure from scratch.&lt;/p&gt;

&lt;p&gt;This is where Amazon Bedrock AgentCore enters the picture. Think of AgentCore as the production bridge. It is an agentic platform designed to host, secure, and operate agents built on any framework—whether it is LlamaIndex, CrewAI, LangGraph, or custom code.&lt;/p&gt;

&lt;p&gt;AgentCore eliminates the undifferentiated heavy lifting of managing agent infrastructure. It provides several modular, serverless services that you can use together or independently:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AgentCore Runtime:&lt;/strong&gt; A secure, isolated, and scalable serverless environment to run your custom agent containers without managing servers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AgentCore Memory:&lt;/strong&gt; A managed memory system that handles short-term and long-term context retention so your agents can build personalized, coherent conversations over multiple sessions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AgentCore Gateway:&lt;/strong&gt; A secure service that converts standard enterprise APIs into Model Context Protocol (MCP) tools, making them instantly discoverable and usable by your agents.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AgentCore Identity:&lt;/strong&gt; Assures compliance and security by assigning unique, verifiable identities to agents, enabling fine-grained access control to enterprise data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AgentCore Observability:&lt;/strong&gt; Real-time tracing and monitoring of agent execution paths, giving you deep visibility to audit reasoning and debug failures in production.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By choosing a custom framework for development and pairing it with Bedrock AgentCore for production deployment, you get the absolute best of both worlds: ultimate open-source flexibility combined with enterprise-grade security, scalability, and managed operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary: Your Decision Matrix&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Amazon Bedrock Agents if you want a managed, configuration-based approach with minimal custom code and rapid deployment.&lt;/li&gt;
&lt;li&gt;Use Strands Agents if you are writing custom code and require native, deep integration with the AWS cloud ecosystem.&lt;/li&gt;
&lt;li&gt;Use LangGraph if your workflow demands highly complex, cyclic state-machine orchestration.&lt;/li&gt;
&lt;li&gt;Use CrewAI if your application is best structured as a collaborative team of specialized, role-based agents.&lt;/li&gt;
&lt;li&gt;Deploy your custom framework of choice using Amazon Bedrock AgentCore to run, secure, monitor, and scale it in production without operational overhead.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>architecture</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
